文章主题:流水, 并行, 时间管理
在我之前的两篇科普文章中,我们已经简要地介绍了流水的技术,以及它在程序性能优化方面的应用。作为一篇初级的科普性文章,我们并没有深入探讨流水的专业细节,而是试图让大家对其有一个直观的认识。
董董灿是个攻城狮:AI加速(三)| 每条指令都是流水线的工人
本篇打算再通过一个生活中的小例子,让大家更直观的了解什么是流水。
举个例子
早晨从起床到上班出门,我们一般会做以下几件事:刷牙、烧水、喝水、出门。
在遵循常规顺序的情况下,我们可能会按照以下步骤进行:首先,刷牙;接着,准备热水;然后,等待水烧开;最后,出门。若每项任务所需时间如表所示,那么在踏出家门之前,我们需要总共花费55分钟。

然而,一旦你对时间管理有所了解,我想你一定会注意到,优先完成洗牙和煮水这样的任务是没有必要的。毕竟,这两项任务之间并无关联,而且在煮水过程中也不需要持续观察。
于是,就有了下面的做事顺序——起来先烧水,然后在烧水的同时,刷牙,等水烧开了,喝水,出门。
这么算下来,总共需要40分钟就能完成。
这两种做事顺序最终的结果都是一样的,而且该做的事都做了。区别在于,后面比前面节省了15分钟的时间。
这里需要注意2个概念。
依赖——后面的事依赖前面的事情。也就是说喝水肯定依赖烧水完成之后才能出门。
并行——烧水和刷牙没有任何依赖关系,他俩就可以并行去做。
在上图中,我们可以看到烧水和刷牙这两个动作在同一时间进行了。因此,我们可以得出结论,在从起床到出门的整个时间流程中,烧水和刷牙实现了并行处理。这样,不仅可以有效地节省15分钟的时间,还能够提高效率,使我们的早晨更加美好。
在理解了并行的概念之后,流水就好理解了。
流水排布到底是什么样的
继续上面的例子,比如我们起床需要刷两次牙,烧两次水,喝两次水。(当然现实中不会有人这么做,但是在AI神经网络中,重复某个计算是常有的事。感兴趣可以看下 长文解析Resnet50的算法原理 中的Rensnet网络结构)。
如果刷两次牙,烧两次水,喝两次水,然后出门,我们该怎么管理时间呢?

在我们的日常生活中,刷牙和烧水、喝水这三个动作肯定是在一定的顺序下进行的,这就像我们按照特定的步骤来完成一项任务一样,这是一个先后顺序的问题。在这个问题上,我们必须明确的是,虽然刷牙和烧水、喝水之间的依赖性是显而易见的,但并不意味着这些动作就不能同时进行。例如,当我们需要烧第二次水的时候,我们其实可以利用第一次烧的水。这就说明,尽管烧水和喝水之间存在一定的依赖关系,但在实际操作中,我们可以灵活地安排这些动作的时间,使它们并行进行,以达到更高的效率。这种做法不仅能够提高我们的生活品质,也能够让我们更好地适应生活的节奏。
在上图中,我们可以看到整个左上角的布局呈现出一种瀑布般的视觉效果,每一行都包含着两个任务的同时进行。尽管这两个任务在同一时刻彼此独立,但是整个系统却依然保持着高度的秩序与协调。
这种排布,就叫做流水。
在指令序列中,将刷牙、烧水、喝水替换成指令,就完成了指令流水;在神经网络中,将刷牙、烧水、喝水替换成AI算法,就完成了算法流水。但是能排流水总是需要满足前面说的两个前提:同一时刻的两件事、或两条指令、或两个算法是解除依赖的,并且可以并行处理的。
说到这,有同学可能会问,既然这样,我们弄两个烧水壶同时烧水不就行了么?
当然可以,这就是升级硬件喽。双核CPU肯定要比单核CPU性能好,就是这个原因了。排流水是在硬件资源有限的前提下,最大限度的减少程序运行时间,提升整个AI软件栈的性能!
Resnet50 中的算法并行
在Resnet50的网络结构(详见:图像识别(番外1)| AI算法攻城狮左手图纸,右手搬砖的真实性以及长图展示Resnet全貌和可视化CNN!)中,存在很多可并行的算法。

上图是截取的Resnet50网络中的一部分,可以看到中间有个加法节点,加法节点有两个输入,分别为左边的卷积1和右边的卷积2(Conv为Convolution的缩写,中文名为卷积)。
左边的卷积1依赖于它前面的Relu的输出,而右边的卷积2依赖于很靠前的某个节点的输出,两者并没有实际上的数据依赖,因此,在深度学习编译器对两个节点进行编译调度时,可以将两者进行并行化处理(Parallelization),从而减少一个卷积运算的耗时。
总结
之所以又花了一篇文章来介绍流水和并行技术,是因为并行和流水技术在AI软件的性能优化中占据了很重要的位置。
在硬件资源有限的前提下,我们只能通过软件手段来持续进行AI的加速优化。这里面,更深刻的理解硬件的架构,利用好硬件的优势,编写更加硬件友好的软件代码,才能更加有效的实现AI加速。
知己知彼,百战不殆。
好了,这篇就介绍到这。欢迎持续关注AI加速系列。
AI时代,拥有个人微信机器人AI助手!AI时代不落人后!
免费ChatGPT问答,办公、写作、生活好得力助手!
搜索微信号aigc666aigc999或上边扫码,即可拥有个人AI助手!