0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

flowflops:OneFlow模型的Flops计算

jf_pmFSk4VX 来源:GiantPandaCV 作者:OneFlow 胡伽魁 2022-11-16 10:04 次阅读

flowflops: OneFlow 模型的 Flops 计算

用于计算 OneFlow 模型的 FLOPs 和 Parameters 的第三方库。

源码地址(欢迎star): https://github.com/Oneflow-Inc/flow-OpCounter

介绍 & 使用

FLOPs & MACs 介绍

有许多人分不清楚 FLOPs 和 MACs 之间的关系,如 ptflops中的issue (https://github.com/sovrasov/flops-counter.pytorch/issues/70)

针对该问题,可以查看 thop中的解释 (https://github.com/Lyken17/pytorch-OpCounter/blob/master/benchmark/README.md),翻译如下:

MACs, FLOPs, what is the difference?

FLOPs 是浮点算子(floating operations)的缩写,包括mul / add / div ...等。

MACs 代表执行的乘法累加运算,例如: a <- a + (b x c)。

如文中所示,一MACs有一mul和一add。这就是为什么在许多地方FLOPs几乎是两倍MACs的原因。

然而,现实世界中的应用要复杂得多。让我们考虑一个矩阵乘法示例。A是一个形状为 的矩阵,B是一个 的向量。

foriinrange(m):
forjinrange(n):
C[i][j]+=A[i][j]*B[j]#onemul-add

它会是m*n个MACs和2m*n个FLOPs。但是这样的矩阵乘法实现速度很慢,需要并行化才能运行得更快。

foriinrange(m):
parallelforjinrange(n):
d[j]=A[i][j]*B[j]#onemul
C[i][j]=sum(d)#nadds

此时MACs数值不再是 m*n 。

在比较 MAC / FLOP 时,我们希望数字与实现无关并且尽可能通用。因此在 thop (https://github.com/Lyken17/pytorch-OpCounter) 中,我们只考虑乘法的次数,而忽略所有其他操作。

安装方法

pipinstallflowflops

使用方法

目前支持两种 FLOPs 计算策略:在 Eager 模式下计算和在 Graph 模式下计算。

在 Graph 模式下计算耗时较长,但结果更加精确

示例:

importoneflowasflow
importflowvision.modelsasmodels
fromflowflopsimportget_model_complexity_info


model=models.resnet50()#yourownmodel,nn.Module
dsize=(1,3,224,224)#B,C,H,W

formodein["eager","graph"]:
print("======{}======".format(mode))
total_flops,total_params=get_model_complexity_info(
model,dsize,
as_strings=False,
print_per_layer_stat=False,
mode=mode
)
print(total_flops,total_params)

输出:

======eager======
412192509625557032
======graph======
412744445625557032

可以看到两种计算方式下的输出有一定差别,这是因为在 ResNet 的 forward 代码里存在类似 out += identity 的语句,这会造成 FLOPs 额外增加。而在 Eager 模式下我们只关注在 __init__() 中定义的网络层,所以这种情况不会在 Eager 模式中被 hook 到。

我们可以计算一下有哪些 add_n 算子在 Eager 模式中被我们忽略了:

stage-one:(1,256,56,56)*3
stage-two:(1,512,28,28)*4
stage-three:(1,1024,14,14)*6
stage-four:(1,2048,7,7)*3

一共为 5,519,360 ,刚好为两种模式的输出差值 4127444456 - 4121925096 = 5519360

在 Eager 模式下也会存在一些小误差,一般认为 ResNet50 的 FLOPs 为 4.09G ,而这里计算得到 4.12G ,是因为一般研究中会忽略类似 ReLU 等算子的 FLOPs 计算,所以与真实数值会有一定误差。有关一般都忽略了哪些算子的计算,可以查看 fvcore 的输出,该库针对 pytorch 进行开发。

Skippedoperationaten::batch_norm53time(s)
Skippedoperationaten::max_pool2d1time(s)
Skippedoperationaten::add_16time(s)
Skippedoperationaten::adaptive_avg_pool2d1time(s)
FLOPs:4089184256

在ptflops包中也存在这样的问题,笔者也有在issue中回复,详见issue: https://github.com/sovrasov/flops-counter.pytorch/issues/94

Eager & Graph 模式下的 Flops 计算

接下来我们以简单修改后的 ResNet18 中的 BasicBlock 为例介绍一下两种 FLOPs 计算方式,设定网络如下:

我们统一假定输入形状为(1, 32, 64, 64)

importoneflowasflow
importoneflow.nnasnn


defconv3x3(
in_planes:int,out_planes:int,stride:int=1,groups:int=1,dilation:int=1
)->nn.Conv2d:
"""3x3convolutionwithpadding"""
returnnn.Conv2d(
in_planes,
out_planes,
kernel_size=3,
stride=stride,
padding=dilation,
groups=groups,
bias=True,
dilation=dilation,
)


defconv1x1(in_planes:int,out_planes:int,stride:int=1)->nn.Conv2d:
"""1x1convolution"""
returnnn.Conv2d(in_planes,out_planes,kernel_size=1,stride=stride,bias=False)


classBasicBlock(nn.Module):
expansion:int=1

def__init__(
self,
inplanes:int=32,
planes:int=64,
stride:int=1,
downsample=None,
groups:int=1,
dilation:int=1,
norm_layer=None,
)->None:
super(BasicBlock,self).__init__()
ifnorm_layerisNone:
norm_layer=nn.BatchNorm2d
#Bothself.conv1andself.downsamplelayersdownsampletheinputwhenstride!=1
self.conv1=conv3x3(inplanes,planes,stride)
self.bn1=norm_layer(planes)
self.relu=nn.ReLU()
self.downsample=downsample
self.stride=stride
self.fc=nn.Linear(planes,planes)

defforward(self,x):
identity=x

out=self.conv1(x)
out=self.bn1(out)
out=self.relu(out)

ifself.downsampleisnotNone:
identity=self.downsample(x)

out+=flow.cat([identity,identity],dim=1)
out=self.relu(out)

returnself.fc(out)

Eager

在 Eager 模式中,我们只关注 __init__() 中定义的网络层,也就是

self.conv1=conv3x3(inplanes,planes,stride)
self.bn1=norm_layer(planes)
self.relu=nn.ReLU()
self.fc=nn.Linear(planes,planes)

二维卷积

卷积的原理在此不再赘述,直接给出计算公式:

归一化

batchnorm 主要计算了均值、方差,并基于此对特征进行归一化与仿射变换,其 FLOPs 为

如果不进行仿射变换,则其 FLOPs 为

激活函数

relu 对输入(1, C, H, W)进行了 y = x if x > 0 else 0 操作,也就是其 FLOPs 为

线性层

线性层输入为 (N, C, H, W)

线性层权重为 (W1, W)

两者相乘的 FLOPs 为

其本质与 matmul 计算相当

Graph

在 Graph 模式中,我们会将 flow.nn.Module 编译为 flow.nn.Graph ,从 Graph 中抽取出每一个算子输入的张量形状后再对网络的 FLOPs 进行计算

上述网络转换后的 Graph:

(GRAPHMyGraph):(
(CONFIGGraphConfig(training=False,))
(INPUTtensor(...,size=(1,32,64,64),dtype=oneflow.float32))
(MODULEBasicBlock()):(
(INPUTtensor(...,is_lazy='True',size=(1,32,64,64),dtype=oneflow.float32))
(MODULEConv2d(32,64,kernel_size=(3,3),stride=(1,1),padding=(1,1),bias=False)):(
(INPUTtensor(...,is_lazy='True',size=(1,32,64,64),dtype=oneflow.float32))
(PARAMETERtensor(...,size=(64,32,3,3),dtype=oneflow.float32,requires_grad=True)):()
(OPERATOR:model.conv1.weight()->(out:sbp=(B),size=(64,32,3,3),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.conv1-conv2d-0(_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32)),model.conv1.weight/out:(sbp=(B),size=(64,32,3,3),dtype=(oneflow.float32)))->(model.conv1-conv2d-0/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)
(MODULEBatchNorm2d(64,eps=1e-05,momentum=0.1,affine=True,track_running_stats=True)):(
(INPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
(PARAMETERtensor(...,size=(64,),dtype=oneflow.float32,requires_grad=True)):()
(PARAMETERtensor(...,size=(64,),dtype=oneflow.float32,requires_grad=True)):()
(BUFFERtensor(...,size=(64,),dtype=oneflow.float32)):()
(BUFFERtensor(...,size=(64,),dtype=oneflow.float32)):()
(BUFFERtensor(...,size=(),dtype=oneflow.int64)):()
(OPERATOR:model.bn1.running_mean()->(out:sbp=(B),size=(64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.bn1.running_var()->(out:sbp=(B),size=(64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.bn1.weight()->(out:sbp=(B),size=(64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.bn1.bias()->(out:sbp=(B),size=(64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.bn1-normalization-1(model.conv1-conv2d-0/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)),model.bn1.running_mean/out:(sbp=(B),size=(64),dtype=(oneflow.float32)),model.bn1.running_var/out:(sbp=(B),size=(64),dtype=(oneflow.float32)),model.bn1.weight/out:(sbp=(B),size=(64),dtype=(oneflow.float32)),model.bn1.bias/out:(sbp=(B),size=(64),dtype=(oneflow.float32)))->(model.bn1-normalization-1/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)
(MODULEReLU()):(
(INPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
(INPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
(OPERATOR:model.relu-relu-2(model.bn1-normalization-1/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)))->(model.relu-relu-2/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.relu-relu-5(model-add_n-4/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)))->(model.relu-relu-5/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)
(MODULELinear(in_features=64,out_features=64,bias=True)):(
(INPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
(PARAMETERtensor(...,size=(64,64),dtype=oneflow.float32,requires_grad=True)):()
(PARAMETERtensor(...,size=(64,),dtype=oneflow.float32,requires_grad=True)):()
(OPERATOR:model.fc.weight()->(out:sbp=(B),size=(64,64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.fc-broadcast_matmul-6(model.relu-relu-5/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)),model.fc.weight/out:(sbp=(B),size=(64,64),dtype=(oneflow.float32)))->(model.fc-broadcast_matmul-6/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.fc.bias()->(out:sbp=(B),size=(64),dtype=(oneflow.float32)):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model.fc-broadcast_add-7(model.fc-broadcast_matmul-6/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)),model.fc.bias/out:(sbp=(B),size=(64),dtype=(oneflow.float32)))->(model.fc-broadcast_add-7/z_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)
(OPERATOR:model-concat-3([_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32)),_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32))])->(model-concat-3/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:model-add_n-4([model.relu-relu-2/y_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32)),model-concat-3/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))])->(model-add_n-4/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)
(OPERATOR:_MyGraph_0_input.0.0_2(...)->(...):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OPERATOR:_MyGraph_0_output.0.0_2(...)->(...):placement=(oneflow.placement(type="cpu",ranks=[0])))
(OUTPUTtensor(...,is_lazy='True',size=(1,64,64,64),dtype=oneflow.float32))
)

Graph 中由 OPERATOR 开始的层就是我们所需要的信息,我们可以注意到

out+=identity

被转换为

(OPERATOR:model-add_n-3([model.relu-relu-2/y_0:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32)),_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32))])->(model-add_n-3/out_0:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))

这有助于我们更准确的对网络 FLOPs 进行计算。

卷积

在 flow.nn.Graph 中 conv3x3 和 conv1x1 会被拆解为 conv2d + bias_add(if bias==True)

由于我们只关注的卷积层的输入,而在计算 FLOPs 时需要得到卷积层输出的特征尺寸,所以我们需要依据输入计算输出特征的分辨率,方法如下

output_dims=[]
fori,in_diminenumerate(in_dims):
d=math.ceil((in_dim-kernel_size[i]+2*padding[i])/strides[i])+1
if(in_dim-kernel_size[i]+2*padding[i])%strides[i]!=0:
d-=1
output_dims.append(d)

随后即可正常计算 FLOPs

至于为什么不直接得到算子输出的形状,因为解析 Graph 需要占用更多的额外时间

归一化

在 flow.nn.Graph 中 norm_layer(bn) 是一个单独的算子,其计算方法与 Eager 模式中保持一致

需要注意的是 InstanceNorm 和 GroupNorm 在 flow.nn.Graph 中将被拆解为若干胶水算子,需要逐个计算

激活函数

在 flow.nn.Graph 中 relu 是一个单独的算子,其 FLOPs 计算方法与 Eager 模式中保持一致

线性层

在 flow.nn.Graph 中 linear 会被拆解为 matmul + broadcast_add(if bias==True),其 FLOPs 计算公式与 Eager 模式中基本一致

其他

在 flow.nn.Graph 中有一些例如 concat 的算子也会被捕捉,例如上述 Graph 中存在的

(OPERATOR:model-concat-3([_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32)),_MyGraph_0_input.0.0_2/out:(sbp=(B),size=(1,32,64,64),dtype=(oneflow.float32))])->(model-concat-3/out_0:(sbp=(B),size=(1,64,64,64),dtype=(oneflow.float32))):placement=(oneflow.placement(type="cpu",ranks=[0])))

针对此类算子,我们认为其不会影响网络的 FLOPs ,故将其 FLOPs 置为0

目前支持的 Op 与模型

目前该工具支持绝大部分算子、网络层与大多数 CNN ,列表如下

Eager

#convolutions
nn.Conv1d
nn.Conv2d
nn.Conv3d
#activations
nn.ReLU
nn.PReLU
nn.ELU
nn.LeakyReLU
nn.ReLU6
#poolings
nn.MaxPool1d
nn.AvgPool1d
nn.AvgPool2d
nn.MaxPool2d
nn.MaxPool3d
nn.AvgPool3d
#nn.AdaptiveMaxPool1d
nn.AdaptiveAvgPool1d
#nn.AdaptiveMaxPool2d
nn.AdaptiveAvgPool2d
#nn.AdaptiveMaxPool3d
nn.AdaptiveAvgPool3d
#BNs
nn.BatchNorm1d
nn.BatchNorm2d
nn.BatchNorm3d
#INs
nn.InstanceNorm1d
nn.InstanceNorm2d
nn.InstanceNorm3d
#FC
nn.Linear
#Upscale
nn.Upsample
#Deconvolution
nn.ConvTranspose1d
nn.ConvTranspose2d
nn.ConvTranspose3d
#RNN
nn.RNN
nn.GRU
nn.LSTM
nn.RNNCell
nn.LSTMCell
nn.GRUCell

Graph

#conv
"conv1d"
"conv2d"
"conv3d"
#pool
"max_pool_1d"
"max_pool_2d"
"max_pool_3d"
"avg_pool_1d"
"avg_pool_2d"
"avg_pool_3d"
"adaptive_max_pool1d"
"adaptive_max_pool2d"
"adaptive_max_pool3d"
"adaptive_avg_pool1d"
"adaptive_avg_pool2d"
"adaptive_avg_pool3d"
#activate
"relu"
"leaky_relu"
"prelu"
"hardtanh"
"elu"
"silu"
"sigmoid"
"sigmoid_v2"
#add
"bias_add"
"add_n"
#matmul
"matmul"
"broadcast_matmul"
#norm
"normalization"
#scalar
"scalar_mul"
"scalar_add"
"scalar_sub"
"scalar_div"
#stats
"var"
#math
"sqrt"
"reduce_sum"
#broadcast
"broadcast_mul"
"broadcast_add"
"broadcast_sub"
"broadcast_div"
#empty
"reshape"
"ones_like"
"zero_like"
"flatten"
"concat"
"transpose"
"slice"

FlowVision 中部分模型的计算结果

======eager======
+--------------------+----------+-------------+
|Model|Params|FLOPs|
+--------------------+----------+-------------+
|alexnet|61.1M|718.16MMac|
|vgg11|132.86M|7.63GMac|
|vgg11_bn|132.87M|7.64GMac|
|squeezenet1_0|1.25M|830.05MMac|
|squeezenet1_1|1.24M|355.86MMac|
|resnet18|11.69M|1.82GMac|
|resnet50|25.56M|4.12GMac|
|resnext50_32x4d|25.03M|4.27GMac|
|shufflenet_v2_x0_5|1.37M|43.65MMac|
|regnet_x_16gf|54.28M|16.01GMac|
|efficientnet_b0|5.29M|401.67MMac|
|densenet121|7.98M|2.88GMac|
+--------------------+----------+-------------+
======graph======
+--------------------+----------+-------------+
|Model|Params|FLOPs|
+--------------------+----------+-------------+
|alexnet|61.1M|718.16MMac|
|vgg11|132.86M|7.63GMac|
|vgg11_bn|132.87M|7.64GMac|
|squeezenet1_0|1.25M|830.05MMac|
|squeezenet1_1|1.24M|355.86MMac|
|resnet18|11.69M|1.82GMac|
|resnet50|25.56M|4.13GMac|
|resnext50_32x4d|25.03M|4.28GMac|
|shufflenet_v2_x0_5|1.37M|43.7MMac|
|regnet_x_16gf|54.28M|16.02GMac|
|efficientnet_b0|5.29M|410.35MMac|
|densenet121|7.98M|2.88GMac|
+--------------------+----------+-------------+

总结

简单介绍 OneFlow 模型中如何计算网络 FLOPs

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 模型
    +关注

    关注

    1

    文章

    3171

    浏览量

    48711
  • MACS
    +关注

    关注

    0

    文章

    4

    浏览量

    7524
  • OneFlow
    +关注

    关注

    0

    文章

    9

    浏览量

    8791

原文标题:flowflops: OneFlow 模型的 Flops 计算

文章出处:【微信号:GiantPandaCV,微信公众号:GiantPandaCV】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    OneFlow Softmax算子源码解读之WarpSoftmax

    写在前面:近来笔者偶然间接触了一个深度学习框架 OneFlow,所以这段时间主要在阅读 OneFlow 框架的 cuda 源码。官方源码基于不同场景分三种方式实现 Softmax,本文主要介绍其中一种的实现过程,即 Warp 级别 Softmax,适用于矩阵宽度不超过 1
    的头像 发表于 01-08 09:24 757次阅读
    <b class='flag-5'>OneFlow</b> Softmax算子源码解读之WarpSoftmax

    OneFlow Softmax算子源码解读之BlockSoftmax

    写在前面:笔者这段时间工作太忙,身心俱疲,博客停更了一段时间,现在重新捡起来。本文主要解读 OneFlow 框架的第二种 Softmax 源码实现细节,即 block 级别的 Softmax。
    的头像 发表于 01-08 09:26 656次阅读
    <b class='flag-5'>OneFlow</b> Softmax算子源码解读之BlockSoftmax

    国际巨头重金投入,国产深度学习框架OneFlow有何优势?

    的ResNet50-v1.5和BERT-base两个模型中,无论是Float32类型还是自动混合精度,在同样的算法和硬件条件下,吞吐率及加速比均优于其他深度学习框架。 ResNet-50是计算机视觉(Computer
    的头像 发表于 12-17 09:31 4161次阅读

    mos模型的迭代计算找不到

    您好,我使用的是“IC-CAP”软件,因此我可以访问我的MOS晶体管的VerilogA模型。外部电压和流动电流由IC-CAP存储。另外,我在每次调用我的模型时,在一个单独的文件中保存自己的计算
    发表于 12-19 16:29

    TensorFlow、PyTorch,“后浪”OneFlow 有没有机会

    TensorFlow、PyTorch,“后浪”OneFlow 有没有机会 | 一流科技工程师成诚编者按:7月31日,一流科技在创业1300天后,他们宣布开源自研的深度学习框架OneFlow,此前,CSDN对CEO袁进辉进行了专访。本文中,一流科技工程师成...
    发表于 07-27 08:24

    FLOPS和TOPS的区别在哪

    s小写,是floating point operations的缩写(s表复数),意指浮点运算数,理解为计算量, 可以用来衡量算法/模型的复杂度。常用框架的复杂度TOPS(Tera Operatio...
    发表于 07-29 06:48

    请问一下FLOPS、TOPS和FLOPs的区别是什么?

    请问一下FLOPS、TOPS和FLOPs的区别是什么?
    发表于 10-27 07:13

    基于Jini集群网格计算模型及算法

    研究如何使用Jini 来实现集群网格计算环境,给出系统模型JCGE(a Jini-based cluster grid environment),设计一个在此模型上进行并行计算的通用算
    发表于 05-14 11:05 17次下载
    基于Jini集群网格<b class='flag-5'>计算</b><b class='flag-5'>模型</b>及算法

    LabVIEW中可用的几种计算模型

    本文将概括了在LabVIEW中可用的几种计算模型,以及何时使用这些模型的指南。
    发表于 04-25 15:46 21次下载

    开源软件-OneFlow通用深度学习框架

    ./oschina_soft/oneflow.zip
    发表于 06-20 09:26 2次下载
    开源软件-<b class='flag-5'>OneFlow</b>通用深度学习框架

    解析OneFlow Element-Wise算子实现方法

    虽然这种写法非常简单明了,但却存在明显的性能问题。所以这篇文章将基于OneFlow开源的Element-Wise CUDA算子方案来解释如何写一个高性能的Element-Wise CUDA算子。
    的头像 发表于 12-12 10:54 1511次阅读

    解析OneFlow BatchNorm相关算子实现

    可以看到 CUDNN_BATCHNORM_PER_ACTIVATION 被用于非卷积层,在OneFlow中只有当输入Tensor的维度为2时才选取这种模式。而
    的头像 发表于 12-23 15:08 632次阅读

    天数智芯与一流科技完成产品兼容性认证,加速推进AI产业应用与落地

    OneFlow深度学习框架是一流科技自主研发的面向大数据、大模型和大计算的流式人工智能计算框架。相对于其它深度学习框架,OneFlow最大的
    的头像 发表于 05-16 11:20 933次阅读
    天数智芯与一流科技完成产品兼容性认证,加速推进AI产业应用与落地

    Profile工作判断模型计算以及内存瓶颈

    /tutorials/pytorch-profiler/ 和 https://www.deepspeed.ai/tutorials/flops-profiler/ 两篇教程做的,使用DeepSpeed训练模型可以基于这两个教程做一下Profile工作判断
    的头像 发表于 06-26 10:45 1380次阅读

    模型的Scaling Law的概念和推导

    对于Decoder-only的模型计算量(Flops), 模型参数量, 数据大小(token数),三者满足:。(推导见本文最后) 模型
    的头像 发表于 11-29 14:28 2239次阅读
    大<b class='flag-5'>模型</b>的Scaling Law的概念和推导