- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
FLOPS: 浮点运算次数。 MADD: 表示一次乘法和一次加法,这可以粗略认为:MADD=2 * Flops,即((输出一个元素所经历的乘法次数)+(输出一个元素所经历的加法的个数)) * (输出总共的元素的个数) MEMREAD: 网络运行时,从内存中读取的大小,即输入的特征图大小 + 网络参数的大小 MEMWRITE: 网络运行时,写入到内存中的大小,即输出的特征图大小 。
在经典卷积神经网络中,输入特征图通常为 \(H\times W\) (这里假设 \(H,W\) 一致),输入通道数目为 \(C_i\) ,卷积核输入深度通常和输入特征图的输入通道保持一致,其核大小通常为 \(K\) ,输出通道(可以理解为输出深度)通常为 \(C_{out}\) ,除此以外需要考虑填充大小 \(P\) 和步长 \(S\) 。基于上述条件,特征图输出大小 \(M\) 满足
在每一次卷积过程中,每个卷积核与输入特征图上当前步对应的窗口内元素进行逐通道、逐元素相乘并累加;重复多次操作,直至卷积核完整遍历输入特征图,每个卷积层运算次数 flops 满足下述关系:
依据层内相乘,层间相加的准则,经典卷积神经网络模型所有卷积层的时间复杂度满足关系如下( \(N\) 为卷积层的数目):
下面通过一个案例,来具体分析:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 2, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(2)
self.relu1 = nn.ReLU()
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu1(x)
return x
net = Net()
stat(net, (3, 500, 500))
# 输入通道为3 输入特征图大小为500
# 输出特征图大小为(500-7+6)/2+1=250
# Flops=250*250*3*2*7*7=18375000
# MADD=(250*250*2)*((7*7*3)+(7*7*3-1))=36625000
# MemREAD= ((500 * 500 * 3) + (7 * 7 * 3 * 2)) * 4 = 3001176.0 【认为每个参数为FP32,满足四个字节,因此乘4】
# MEMW:250 * 250 * 2 * 4 = 500000
下面给出 thop 的使用方法, thop 只能计算输入为一个矩阵的模型的参数量和FLOPs,实际中的模型可能存在多个输入,如以下案例:
out = model(detections,boxs,grids,masks,captions)
# 其中作为模型传入参数的是五个矩阵,其尺寸为:
detections.shape = (bs,50,2048)
boxs.shape = (bs,50,4)
grids.shape = (bs,49,2048)
masks.shape = (bs,50,49)
captions.shape = (bs,19)
想要计算这样一个模型的参数量和计算量,需要考虑一种新的方式。我在这里给出的方案是:构建一个新的,接收单矩阵输入的类。代码如下:
import torch.nn as nn
class func(nn.Module):
def __init__(self,object):
super(func,self).__init__()
self.model = object
def forward(self,a):
detections = torch.randn(1,50,2048).float()
boxs = torch.randn(1,50,4).float()
grids = torch.randn(1,49,2048).float()
masks = torch.randn(1,50,49).float()
captions = torch.tensor([0,100,105,2,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1]).unsqueeze(0)
print(captions.shape)
out = self.model(detections,boxs,grids,masks,captions)
return out
可以看到,该类继承自nn.Module,以确保该类可以被声明为一个模型。接着在类的初始化函数中,将待计算模型的对象作为参数传入,并赋值给self.model;在forward函数中,规定其必须接收一个参数(实际上我们并不会使用这个接收到的参数),并通过torch内置的随机函数产生需要形状的张量(之所以特殊对待captions是因为model要求该参数的元素为整型).
最后,就可以进行参数量和FLOPs的计算,代码如下:
model = Transformer(text_field.vocab.stoi['<bos>'],
encoder, decoder, args=args)
use_model = func(model)
input = torch.randn(1, 3, 224, 224)
flops, params = profile(use_model, inputs=(input))
print("FLOPs=", str(flops/1e9) + '{}'.format("G"))
print("params=", str(params/1e6) + '{}'.format("M"))
其中,第一行声明Transformer类,并将其对象命名为model;第二行声明上面定义的func类,将model作为声明类时的传入参数;第三行随机生成一个矩阵;第四行调用thop中的profile方法对func类的参数量和运算量进行计算,实际上等价于对Transformer类的参数量和运算量计算.
吞吐量:完成一个特定任务的速率(单位时间内完成的任务数目,衡量指标为 bits/second , Bytes/second )。对神经网络而言,吞吐量可以设置为每秒处理的图片数量或语音数量。 延时:完成一个任务需要花费的时间.
吞吐量和延时并不是严格的反比关系。吞吐量可以认为是一个系统并行处理的任务量,延时是一个系统串行处理一个任务所花费的时间 。
optimal_batch = 160000 # 基于本案例中的模型所测试出的最佳batch为160000
# while True: # 这里是确定最佳batch的大小 出现cuda显存不足前认为是最佳batch
# x = torch.randn(optimal_batch, 3, 28, 28).to(device='cuda')
# _ = net(x)
# print("当前测试批量为:", optimal_batch) if optimal_batch % 1000 == 0 else None
# optimal_batch += 100
input = torch.randn(optimal_batch, 3, 28, 28).to(device='cuda')
repetitions = 100
total_time = 0
with torch.no_grad():
for rep in range(repetitions):
starter, ender = torch.cuda.Event(enable_timing=True), torch.cuda.Event(enable_timing=True)
starter.record()
_ = net(input)
ender.record()
torch.cuda.synchronize()
curr_time = starter.elapsed_time(ender) / 1000
total_time += curr_time
Throughput = (repetitions * optimal_batch) / total_time
print('Final Throughput:', Throughput)
[1] 面试宝典笔记:卷积计算过程中的FLOPs [2] 通过thop计算模型的参数量与运算量(FLOPs) [3] THOP+torchstat 计算PyTorch模型的FLOPs,问题记录与解决 [4] 吞吐和时延 [5] 深度学习模型推理速度/吞吐量计算 。
最后此篇关于理性分析不同模型的性能指标的文章就讲到这里了,如果你想了解更多关于理性分析不同模型的性能指标的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有 table 像这样 -------------------------------------------- id size title priority
我的应用在不同的 Activity (4 个 Activity )中仅包含横幅广告。所以我的疑问是, 我可以对所有横幅广告使用一个广告单元 ID 吗? 或者 每个 Activity 使用不同的广告单元
我有任意(但统一)数字列表的任意列表。 (它们是 n 空间中 bin 的边界坐标,我想绘制其角,但这并不重要。)我想生成所有可能组合的列表。所以:[[1,2], [3,4],[5,6]] 产生 [[1
我刚刚在学校开始学习 Java,正在尝试自定义控件和图形。我目前正在研究图案锁,一开始一切都很好,但突然间它绘制不正确。我确实更改了一些代码,但是当我看到错误时,我立即将其更改回来(撤消,ftw),但
在获取 Distinct 的 Count 时,我在使用 Group By With Rollup 时遇到了一个小问题。 问题是 Rollup 摘要只是所有分组中 Distinct 值的总数,而不是所有
这不起作用: select count(distinct colA, colB) from mytable 我知道我可以通过双选来简单地解决这个问题。 select count(*) from (
这个问题在这里已经有了答案: JavaScript regex whitespace characters (5 个回答) 2年前关闭。 你能解释一下为什么我会得到 false比较 text ===
这个问题已经有答案了: 奥 git _a (56 个回答) 已关闭 9 年前。 我被要求用 Javascript 编写一个函数 sortByFoo 来正确响应此测试: // Does not cras
所以,我不得不说,SQL 是迄今为止我作为开发人员最薄弱的一面。也许我想要完成的事情很简单。我有这样的东西(这不是真正的模型,但为了使其易于理解而不浪费太多时间解释它,我想出了一个完全模仿我必须使用的
这个问题在这里已经有了答案: How does the "this" keyword work? (22 个回答) 3年前关闭。 简而言之:为什么在使用 Objects 时,直接调用的函数和通过引用传
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: what is the difference between (.) dot operator and (-
我真的不明白这里发生了什么但是: 当我这样做时: colorIndex += len - stopPos; for(int m = 0; m < len - stopPos; m++) { c
思考 MySQL 中的 Group By 函数的最佳方式是什么? 我正在编写一个 MySQL 查询,通过 ODBC 连接在 Excel 的数据透视表中提取数据,以便用户可以轻松访问数据。 例如,我有:
我想要的SQL是这样的: SELECT week_no, type, SELECT count(distinct user_id) FROM group WHERE pts > 0 FROM bas
商店表: +--+-------+--------+ |id|name |date | +--+-------+--------+ |1 |x |Ma
对于 chrome 和 ff,当涉及到可怕的 ie 时,这个脚本工作完美。有问题 function getY(oElement) { var curtop = 0; if (oElem
我现在无法提供代码,因为我目前正在脑海中研究这个想法并在互联网上四处乱逛。 我了解了进程间通信和使用共享内存在进程之间共享数据(特别是结构)。 但是,在对保存在不同 .c 文件中的程序使用 fork(
我想在用户集合中使用不同的功能。在 mongo shell 中,我可以像下面这样使用: db.users.distinct("name"); 其中名称是用于区分的集合字段。 同样我想要,在 C
List nastava_izvjestaj = new List(); var data_context = new DataEvidencijaDataContext();
我的 Rails 应用程序中有 Ransack 搜索和 Foundation,本地 css 渲染正常,而生产中的同一个应用程序有一个怪癖: 应用程序中的其他内容完全相同。 我在 Chrome 和 Sa
我是一名优秀的程序员,十分优秀!