神经网络推理加速入门——超简单的卷积和加法融合—伪代码版

简介: 用一个伪代码,学习卷积和加法如何融合的。

大家好啊,我是董董灿。

前几天写了一个卷积神经网络(CNN)中,卷积和加法融合的文章。有同学发私信,希望写一个带代码版本的,方便更好的理解。

我的第一反应是,代码版本的咋写,有那么多细节。后来一想,其实那位同学想知道的并不是那些细节,而是一个大致的流程。

于是我说,行,那我写一个伪代码版的吧,把大致的代码思路写一下。

至于具体卷积算法怎么实现的,建议chatGPT一下,或者看下开源深度学习仓库就行。

如果没看之前的文章,可以看上一看:超简单的卷积和加法融合

开始分析

还是以 resnet50 中的图为例,做一个卷积和加法的融合。

image.png

正常情况下,上述网络片段在执行的时候大概是这样的:

BatchNorm -> Relu -> Conv -| Add的左分支
                           |                -> Add
                  -> Conv -| Add的右分支

写出伪代码,实际上就是一种顺序调用逻辑,比如

bn_out = Batch_normal();
relu_out = Relu(bn_out);
conv_out_left = Conv2d(relu_out)
conv_out_right = Conv2d(...)
add_out = Add(conv_out_left, conv_out_right)

而一旦融合完之后,上图红框中的Conv 和 Add 就变成了一个算子,这里暂且称这个融合之后的算子为 ConvAdd 算子。

于是,上述的图,就变成了如下的图:

image.png

此时,整个网络片段的调用逻辑变成了:

bn_out = Batch_normal();
relu_out = Relu(bn_out);
conv_out_right = Conv2d(...)
add_out = ConvAdd(relu_out, conv_out_right)

再把 ConvAdd 当做一个算子之后,便可以进行很多融合、拆图、流水并行操作。

假设现在这个网络运行在一个Asic芯片上,芯片上卷积计算模块和加法计算模块是互相独立的,没有任何依赖。

这里假设卷积输入的 Feature Map 的大小是 [n, hi, wi, ci],卷积核是[co, kh, kw, ci]。

其余参数简化一下,将卷积 pad 简化为0,stride 简化为1,dilation简化为1。

卷积的输出为[n, ho, wo, co]。

那么卷积后面的加法,执行的两个tensor相加,也就变成了 [n, ho, wo, co] + [n, ho, wo, co] = [n, ho, wo, co]。

那么,我们将卷积的输入(假设是下面的一张图),在H方向切成两份。

image.png

那么计算完一整张图,需要调用两次卷积运算,第一次计算上半部分,第二次计算下半部分。

两次计算中,大部分像素之间是没有关系的,仅仅在两部分交界的地方会有可能存在依赖。(存在依赖的条件为 kernel 大于1,或者 stride 大于1,这些情况先不考虑,暂时认为两部分像素没有关系)。

那么第一次卷积计算,计算的输入是 [n, hi/2, wi, ci],计算输出结果是 [n, ho/2, wo, co]。此时计算的是前半部分的 hi。用红色表示。

那么第二次卷积计算,计算的输入是 [n, hi/2, wi, ci],计算输出结果是 [n, ho/2, wo, co]。此时计算的是后半部分的 hi。用蓝色表示。

同理,加法也会被分成两次计算,分别对应计算卷积的两次输出:

  • 第一次加法,计算的是第一次卷积的输出,即 [n, ho/2, wo, co]
  • 第一次加法,计算的是第一次卷积的输出,即 [n, ho/2, wo, co]

那么,在两次计算的情况下,ConvAdd 这一个算子中,内部的实现逻辑大致应该是:

conv_out_part1 = Conv2d(part1)
conv_out_part2 = Conv2d(part2)
add_out_part1 = Add(conv_out_part1)
add_out_part2 = Add(conv_out_part2)

但是这样显然是不行的,因为这样写还是串行执行:执行完第一次卷积执行第二次卷积,执行完第二次卷积执行第一次加法...

那怎么让 Conv 和 Add 并行起来呢?

通过观察可以发现,第一次的Add并不依赖第二次的Conv,并且我们已经假设了Asic芯片上Conv运算模块和Add模块完全独立。

那么让第二次Conv和第一次Add并行起来的方法就是:第一次Conv计算完之后,直接计算第一次Add,然后同时并行第二次Conv,这个时候,代码的实现大致是这样:

conv1 = Conv2d(part1)
-----------------------
add1 = Add(conv1)      
conv2 = Conv2d(part2) 
-----------------------
add2 = Add(conv2)

这个时候,Add 和 conv 在中间的一个流水级中并行起来了。

所谓的一个流水级,指的是上面代码段中两个“ ------ ” 之间的代码,称之为在一个流水级中。

那如果将图片拆成更多份,那可以并行的流水级就会更多。

比如拆成4份,那可以有3个流水级中的Conv和Add并行起来。

conv1 = Conv2d(part1)
-----------------------
add1 = Add(conv1)      
conv2 = Conv2d(part2) 
-----------------------
add2 = Add(conv2)
conv3 = Conv2d(part3) 
-----------------------
add3 = Add(conv3)      
conv4 = Conv2d(part4) 
-----------------------
add4 = Add(conv4)      
-----------------------

需要说明一点的是,上面伪代码中,每一个 “-----” 其实都代表了一个同步点。

在实际部署到硬件上运行时,需要在这些同步点上设置同步操作,用来使上一个流水级中的所有计算操作全部完成即可。

常用的同步操作有一些同步指令或者barrier指令。假设我们使用barrier指令来进行同步,那么上述完整的伪代码便是:

conv1 = Conv2d(part1)
barrier()

add1 = Add(conv1)      
conv2 = Conv2d(part2) 
barrier()

add2 = Add(conv2)
conv3 = Conv2d(part3) 
barrier()

add3 = Add(conv3)      
conv4 = Conv2d(part4) 
barrier()

add4 = Add(conv4)      
barrier()

当然上述代码看起来太长了,可以写成循环的形式,还是以将H方向拆分 4 份为例:

conv1 = Conv2d(part1);
barrier();

for i in range(1, 4):
    add_i = Add(convi)
    Conv_i+1 = Conv2d(part_i+1)
    barrier()

add4 = Add(conv4)      
barrier()

伪代码的逻辑还是很简单的,关键是需要理解Conv和Add并行流水的思想。

这种方法可以用到的融合场景很多,并不仅仅局限于Conv和Add这两个算子,也不局限于某一个神经网络。

只要是在硬件上计算单元可以并行执行,并且在神经网络结构图上前后有依赖的层,几乎都可以这么进行融合来提升整体性能。

欢迎关注@董董灿是个攻城狮 和同名微信公众号
本文作者原创,转载请联系作者,请勿随意转载

相关文章
|
19天前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
212 55
|
29天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
155 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
18天前
|
机器学习/深度学习 算法 PyTorch
基于图神经网络的大语言模型检索增强生成框架研究:面向知识图谱推理的优化与扩展
本文探讨了图神经网络(GNN)与大型语言模型(LLM)结合在知识图谱问答中的应用。研究首先基于G-Retriever构建了探索性模型,然后深入分析了GNN-RAG架构,通过敏感性研究和架构改进,显著提升了模型的推理能力和答案质量。实验结果表明,改进后的模型在多个评估指标上取得了显著提升,特别是在精确率和召回率方面。最后,文章提出了反思机制和教师网络的概念,进一步增强了模型的推理能力。
46 4
基于图神经网络的大语言模型检索增强生成框架研究:面向知识图谱推理的优化与扩展
|
11天前
|
JSON Dart 前端开发
鸿蒙应用开发从入门到入行 - 篇7:http网络请求
在本篇文章里,您将掌握鸿蒙开发工具DevEco的基本使用、ArkUI里的基础组件,并通过制作一个简单界面掌握使用
47 8
|
1月前
|
机器学习/深度学习 资源调度 算法
图卷积网络入门:数学基础与架构设计
本文系统地阐述了图卷积网络的架构原理。通过简化数学表述并聚焦于矩阵运算的核心概念,详细解析了GCN的工作机制。
85 3
图卷积网络入门:数学基础与架构设计
|
22天前
|
Web App开发 网络协议 安全
网络编程懒人入门(十六):手把手教你使用网络编程抓包神器Wireshark
Wireshark是一款开源和跨平台的抓包工具。它通过调用操作系统底层的API,直接捕获网卡上的数据包,因此捕获的数据包详细、功能强大。但Wireshark本身稍显复杂,本文将以用抓包实例,手把手带你一步步用好Wireshark,并真正理解抓到的数据包的各项含义。
74 2
|
30天前
|
存储 安全 网络安全
云计算与网络安全:技术融合的双刃剑
在数字化浪潮中,云计算如同一股不可阻挡的力量,推动着企业和个人用户步入一个高效、便捷的新时代。然而,随之而来的网络安全问题也如影随形,成为制约云计算发展的阿喀琉斯之踵。本文将探讨云计算服务中的网络安全挑战,揭示信息保护的重要性,并提供实用的安全策略,旨在为读者呈现一场技术与安全的较量,同时指出如何在享受云服务带来的便利的同时,确保数据的安全和隐私。
27 6
|
28天前
|
机器学习/深度学习 人工智能 自然语言处理
深入理解深度学习中的卷积神经网络(CNN)##
在当今的人工智能领域,深度学习已成为推动技术革新的核心力量之一。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,因其在图像和视频处理方面的卓越性能而备受关注。本文旨在深入探讨CNN的基本原理、结构及其在实际应用中的表现,为读者提供一个全面了解CNN的窗口。 ##
|
29天前
|
存储 人工智能 安全
云计算与网络安全:技术融合与挑战
在数字化时代的浪潮中,云计算和网络安全已成为推动社会进步的两大关键技术。本文将探讨云计算服务的发展,网络安全的重要性,以及信息安全技术的演进。我们将通过实例分析,揭示云服务如何增强数据保护,网络安全措施如何应对新兴威胁,以及信息安全技术的创新如何为企业带来竞争优势。文章旨在为读者提供对云计算和网络安全领域的深入理解,并展示它们如何共同塑造我们的未来。
|
29天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
70 3

热门文章

最新文章