最近,很多芯片公司-其中比较重要的包括英特尔和 IBM,还有一众 Arm 芯片厂商和 AMD——推出了具有原生人工智能 (AI) 及其相关机器学习 (ML) 计算能力的新型 CPU 设计。 之前,我们曾经广泛介绍了对专门设计用于支持机器学习算法的数学引擎的需求,特别是用于推理工作负载和某些特定类型的训练的数学引擎。

 

为了只讨论其中一些相关的问题,大家可以考虑一下IBM即将推出的“Cirrus”Power10 处理器,该处理器将搭载在几天后推出的 Big Blue 的高端 NUMA 机器上,具有旨在加速机器学习的新矩阵数学引擎,或者想一想IBM明年推出的“Telum”z16大型机处理器,它在最近的Hot Chips大会上亮相,有一个专用的供CPU核心共享的混合精度矩阵数学内核引擎。同时,英特尔正在将其高级矩阵扩展 (AMX)引擎 添加到其未来的“Sapphire Rapids”至强 SP 处理器中,这款处理器本来现在应该已经上市了,但是因为诸多原因已被推迟到明年年初。 此外,Arm 公司打造了未来的 Arm 核心设计,即“Zeus”V1 核心和“Perseus”N2 核心,它们将拥有更广泛的矢量引擎,支持通常用于机器学习推理的混合精度数学计算。来自 AMD 的“米兰”Epyc 7003 处理器中的矢量引擎也具有类似的计算能力。

 

所有这些芯片都旨在保证在 CPU 上执行推理,在很多情况下,由于数据安全性、数据合规性和应用程序延迟等原因,推理必须在 CPU 上进行。

 

我们之前已经讨论过了硬件,但我们还没有真正深入探讨所有这些数学引擎功能对于那些试图弄清楚如何将机器学习融入到其应用程序中的人的真正意义。所以,我们现在要尝试一下对这些数字引擎进行解读,它意味着你将怎样编程,以使得神经网络可以利用这些芯片厂商提供的计算引擎并满足一定的性能。如果你能做到这一点,那么你将留下比较深刻的印象。事实证明,鉴于我们今天对 AI 的了解,他们的解决方案比添加诸如 DO_AI 之类的指令更加优雅和方便。

 

因此,为了在讨论处理器架构之前让所有人都处在同一个认知水平线上,让我们从代表小型神经网络的常见图片开始。

 

这张图代表了我们今天认为大脑中的神经元正在做什么的最佳模型。我想,大家应该都知道我们大脑的神经元使用模拟电化学在神经元之间进行消息传递,在人工神经网络这里,我们谈论的消息是数字、链接和概率——这也是今天的计算机能够处理的东西。左边的输入是数字,右边的输出也是数字,上面的每个节点代表一组数字,甚至它们之间的这些链接也是数字形式的链接。神经网络的秘诀就在于在左侧引入大量的、远远超过此处所能显示的数量的数字,通过中间这个蓝色的过滤器运行它,然后在右侧筛选出有意义的数字。 

 

请允许我强调一点,这张图片只是对 AI 模型中经常发生的事情的一个非常微小的表示。正如您稍后将在另一个相对简单的例子中所看到的那样,你可以把这个图片想象成可能高很多倍,具有更多的节点,因此也有更多的链接 - 支持多兆字节甚至数百千兆字节的数据结构在今天的神经网络里并不鲜见。整个事情都需要编程——不,实际上是在内部训练——用其他数字来从合理的输入中产生合理的输出。为什么我在这里提到这个?因为现在的性能!这一切都可以完成,而且今天做得很好,现在没有专门的硬件,但是对这个网络的训练时间可能需要......好吧,太长了,我们都希望它更快。现在够快吗?嗯,当然算不上快,也许再等上个 10 到 20 年,等到人工智能的下一场革命发生时才能实现真正的‘快’。 


所以,计算速度和数量与网络尺寸密切相关。让我们从一个故事开始,以引出一个相对简单的例子吧。我的女儿(已经成年)借了我在明尼苏达挂牌的皮卡车在爱荷华州拉了一辆拖车,后来她在那里超速行驶,结果被拍下了卡车的照片。我们在明尼苏达州收到了一张自动传票,要我缴纳罚款,并附上了一张照片。我对这件事很生气,但同时也很好奇。从那个 JPEG 图片到把我给找出来,中间经历了一个什么样的过程?我认为这里面就涉及到了人工智能。 

 

所以,让我们从在明尼苏达挂的这个车牌开始。这个车牌可读性和分辨率都很高(512 个水平像素),可能大于相机的能力,但也可能比神经网络的输入所需的要大得多。不过,这里的重点是要注意,一旦在照片中找到车牌,就必须根据这些像素确定状态并找出大约 6-8 个字符的文本。 

 


以这个尺寸的 1/8 ,测速相机可能会拍下这样的小图像:

 


当你真正看到它时,我们会发现是下面这个画面:
 


人工智能应用程序可能能够整理出许可证号码——毕竟你显然也可以猜出号码来——但也许不知道来自哪个州。因此,让我们将分辨率提高一倍,并转到尺寸的 1/4(128 个水平像素),如下所示:



然后如果再放大一下:
 


也许还有一些不太合理的东西,但让我们选择这个尺寸吧。根据文件的详细信息,该图像的大小为128x65像素。我们也假设某种形式的灰度,假设每像素一个字节。总之,我们可以调用8192个字节来表示所有这些像素。如果爱荷华州不关心明尼苏达州的土地上是不是有1万个湖泊,那它还会稍微小一点。爱荷华州的人工智能模型需要将代表像素的8192个字节转换为文本字符——其中最多8个——以及一个州ID,以便随后在爱荷华州政府可访问的明尼华州数据库中进行查找。这8192字节,即上图中每个黄色垂直输入节点中的一个字节,是您输入到爱荷华州神经网络中的参数集。

 

回顾上面的图,您会注意到每个(黄色)输入字节,经过一些数学运算,将被传递到下一个(最左边的蓝色)层的每个节点。这种运算正是增强型硬件的用武之地,但我需要建立一个足够的基础来了解增强硬件为何会造成一些不同,可能有些啰嗦了,但是请各位看官多多包涵。

 

接下来,这个神经网络最初还只是一大堆空的蓝色节点。对于模型,首先知道它是“一个车牌,但是具体的车牌号是什么?”它需要接受训练才能识别出任何一个车牌出来。请记住,黄色节点的输入值会随着车牌而变化,并且有数百万个不同的值。爱荷华州预计,对于所有这些车牌中的很大一部分,来自大约 49 个州,该网络能够在右侧输出最多 8 个字符以及州 ID。很明显,一个空的神经网络啥也干不了。需要把网络准备好——经过训练——通过反复向网络展示数十万个车牌来进行训练,每次根据输出对网络内部进行细微调整。当然,我不会在这里带你了解如何调整这个网络的各个节点的科学知识,你现在可以只是将它想象成一个很多次的迭代过程,随着调整模型内部结构的过程的继续,成功率将不断提高。简而言之,机器需要学习(如在机器学习中)如何解释任何汽车牌照,并将灰度像素转换为字符。

 

再一次,我又越来越接近硬件了。

 

在下图中,我从上面的神经网络图中获取了输入层,并展示了这些输入经过一级数学处理后的下一层输出,这里只有下一层的两个节点——一个绿色,一个蓝色。同样,请记住,在下一个(以及下一个和再下一个)层级中有许多垂直节点。您会注意到那里显示了一个函数。该函数采用每个单独的输入值 (Ii),将其乘以相关的加权值 (Wi),然后将所有这些乘积值相加。添加一个偏置值,用作网络下一级的输入,函数的最后一步执行一种缩放。换句话说,给定绿色节点,它将所有黄色输入节点表示的值作为输入,将每个值乘以相关的绿色权重值 (Wi),然后将所有这些乘积相加。经过偏置和其他功能调整后,这成为绿色节点的输出。因此,再次将其与我在下面再次展示的整体图表进行比较,以得到一个更大的图景。然后是对每个后续节点重复执行,随着提供更多输入而几乎无限重复下去,这个过程会导致这些权重值发生变化,最终导致输出成功的可能性很高。

 


记住这些乘法和后续的加法。我们这里给出的车牌过滤器只是一个相对较小的例子。在这个神经网络的训练部分,随着每个权重值的调整,我们一遍又一遍地进行训练。 (调整权重值的过程本身很有趣,但与相关的硬件增强并不真正相关。神经网络的训练是改变这些权重的过程,直到整体输出与您期望的一致。)这些操作的频率是性能的关键决定因素。如果您希望神经网络的训练速度更快,则需要整个算法的整体加速。

 

我相信,英特尔的工程师们会很感激我展示他们的架构并为之点赞,但如果可以的话,我将在接下来的几段中重点介绍 IBM 的 Power10 工程师为增强硬件所做的工作。

 

为了对他们所做的事情有一个初步的了解,也许可以从关注这些蓝色节点中的任何一个开始。您会看到该类型神经网络的输入是一组 8192 个黄色节点的灰度值。 (请记住,我们现在正在讨论上面的那个车牌。)然后另一个算法的输入是一组 8192 个加权值((Wi))—一与前面的每个节点相关联。让我们把它想象成两个字节型数据的数组——一个是灰度字节,另一个是加权字节。

 

这时候,可能有的程序员会说了,不,你说的太简单了,我会将黄色节点本身定义为一个数组或一些对象列表。是的,你可能会这么做,但我们在这里谈论的是软件/硬件接口,所以还是忽略这些无关的细节吧。你想让它更快一些吗?然后,您以硬件希望看到的方式将数据提供给硬件,即输入参数数组和权重数组。所以,请暂时给我个面子,就假定这里用的就是字节数组吧。


硬件的硬核知识点


好的,作为一个起点,我们有了大量的数据,我们将针对这些数据一遍又一遍地重复执行相同的操作。然后,为了训练我们的模型,我们将一次又一次地调整数据。当然,您希望快速完成整个枯燥得该死的事情——比没有增强硬件的情况要快得多。不知何故,我们还需要将所有这些数据从 DRAM 中提取到处理器中,然后将其呈现给内核中的一个小功能块,以对其进行实际的数学运算。

 

你们中的一些人可能已经想到了我在暗示的内容:向量处理器的明显用途。是的。因此,对于那些不熟悉矢量处理器概念的人,请坚持住,这是您要了解的第一个硬核知识点。

 

您知道,处理器内核里有乘法器和加法器,以及采用几个数据操作数并将它们进行互相传递的指令集。您最好把它想象成在同一时刻执行一次乘法和一次加法。(当然实际情况并不完全是这样,但对于一个初学者来说,这样理解已经足够了。)每一次执行都需要时间——当无限重复时,时间就会累积起来。因此,考虑到数据就在靠近硬件算术单元的地方,一次完成一次乘加运算,您怎么样才能使其运行得更快呢?如果对现在就在硬件中且可用的数据一遍又一遍地进行相同的操作,您可以同时通过多个算术单元传递多个可用数据,然后所有这些结果都在执行下一次运算的同时并行保存在硬件寄存器中。向量处理单元,一次不是处理一个数据,而是一次并行处理多个数据-处理器内核中已经准备好的一组数据。人工智能领域的新进展就是新的硬件可以一次执行多次乘法和加法。

 

我在上一段中提到了寄存器,这是一种能够将其数据直接(以皮秒为单位)馈送到向量硬件的存储形式。所以,另一个硬核知识点旨在让你了解正在发生的事情。我们在基于车牌的那个小例子中一直在讨论字节数组,其实我们也可以谈论大小为 16 位或 32 位的单位以及这些整数和浮点数。 (更具体地说,在 IBM 的 Power10 中,每个内核有 8 个向量单元来执行这些操作,并且如果需要该级别的吞吐量,则每个内核都支持 FP32、FP16 和 Bfloat16 操作,还有四个支持 INT4、INT8 和 INT16 操作。 ) 要将这些数据并行地输入向量化乘加单元——在这个例子中是连续字节——,数据是在同一时刻从各个寄存器并行读取的。您将在下面看到这一点。好吧,这就是硬件发挥作用的地方。但关键是将缓存/DRAM 中的多个字节加载到这些寄存器中,所有这些都作为单个操作。硬件可以并行执行操作,它只需要软件来确保操作数(连续字节)也并行呈现给硬件寄存器。也有与向量单元相关的加载/存储指令。请注意,最后一个是人工智能模型中保存的数据结构的函数。

 

我试图在下面表示它,最上面的这张图表示数组形式的字节(并且有连续的字节无限期地继续出现)。它是您在此处看到的字节 — X[0][0] 到 X[3][3],它们在单个操作中加载到单个寄存器中(在 Power 架构中称为 VSR)。

 

 

至于下面这个图的其余部分,再次回到硬件的向量运算,单个指令获取 VSR(X) 中的所有数据,并使用 VSR(Y) 中的所有数据进行乘加运算,将结果放入一组称为累加器 (ACC) 的四个寄存器中。由于细节太多,尽管它是作为单个操作完成的,但您可以将 VSR(X) 中的红色参数与 VSR(Y) 中的所有红色参数相乘,橙色与所有橙色相乘,接着是绿色与绿色、蓝色和蓝色,然后在整个 VSR(X) 中使用相同的配色方案向右重复。基本上是同时在图中找到的多个蓝色节点,这些全在一个操作中进行。继续向下遍历先前的数组只是意味着并行循环加载数组的后续部分,并执行在先前累积的结果中折叠的另一条指令。一次执行一整套(这里是 16 个项目)的操作循环。所有这些都从缓存并行高效地馈送,并将结果高效地返回到缓存。

 

令人印象深刻的优雅补充。但是,需要对数据的组织和硬件之间的关系有所了解才能充分利用它。


然后是缓存


我将在这里分析的并不算是对人工智能/机器学习领域的真正补充,因为缓存是允许将驻留在 DRAM 中的数据结构馈送进入处理器芯片上每个内核的微小硬件中执行计算的先决条件——缓存可以帮助高效并行地做这件事。您会看到,内核实际上从未接触过 DRAM。是的,他们没有直接接触DRAM,它们中间隔着缓存!内核访问它们的缓存(顺便说一句,每个内核都有多兆字节缓存,拥有多个内核的芯片的缓存则更多),缓存由 DRAM 内存内容中的连续字节块组成。一旦进入缓存,如果这些块在相对不久的将来被重用,我们就不会受到 DRAM 访问延迟的影响。

 

内核从这些缓存行(那些内存块)中读取数据,以字节为单位或一直到以 16 个字节为单位(就是您在上面看到的128 位),而内核中那些大得多的功能快则直接访问 DRAM 。由于访问 DRAM 比访问缓存需要更多的时间,因此,保持性能的关键是最大限度地减少 DRAM 访问(也称为缓存填充)的次数。这样做的诀窍是确保那些被访问的块中只包含所需要的块。所以,再次回到那些字节数组,你希望硬件式的访问,比如说将这些数组中以 128 字节为单位存到它的缓存中,然后几乎立即流式传输到下一个128字节,直到完成所有读取,这之中几乎没有真正的延迟。硬件希望将这些数组(而不是其他任何东西)流式传输到其缓存中。然后,从这些缓存的块中,一次快速并行加载寄存器 16 个字节。

 

将人工智能神经网络图驻留在内存中,然后如您在上面看到的流程那样处理它,感觉整个过程就像一个经过精心调校的管弦乐队一样,只有乐符和数据的流动。硬件和软件工程师规划的架构亦正如乐队一般。如果软件的数据结构与处理器的架构匹配得很好,那一切都很好。但如果匹配得不好,那就好像管弦乐队出现了演奏的间断,而小提琴还始终在低音范围内演奏一样。任何优秀的贝斯手都给我留下了深刻的印象,但在这种情况下,最好是拉小提琴。

 

边缘设备的人工智能/机器学习


考虑到我那个超速者被罚单的例子的处理速度可能很慢,我可以想象出来,边缘设备上的速度传感器/相机只是将完整的(尽管受加密保护的)JPEG 传递到单个服务器进行处理,而之前的那里使用的训练有素的 AI 模型是相对静态的。当然,这些边缘处理器可能已经接收了今天的静态模型,边缘设备通过该模型对 JPEG 完成实际过滤。但在更普遍的人工智能/机器学习的世界中,这些模型并不总是静态的。也不能让所有的应用程序都接受隐含的更长的延迟。此外,边缘处理器很可能需要在自己的本地环境中对模型进行一些调整;它发现自己所处的环境可能会决定一种微妙不同且积极变化的模型。

 

也许在那里没有那么多机器学习和全面训练,但在某些情况下需要在本地更改模型。然而,(重新)训练游戏与我们上面看到的并没有什么不同,而且通常要大得多。而且,这种训练需要在边缘进行。在边缘使用的模型是否产生了正确的结果,如果它以某种方式关闭,如何使其恢复到预期的范围内?而且,我们需要在不影响人工智能模型的正常使用的情况下动态即时地执行此操作,同时这个工作负荷要在边缘设备的计算能力和功率范围内。我们在这里谈论的不一定是高性能计算机级系统--它具有专门用于机器学习的专门系统插件的东西。 人工智能/机器学习所隐含的这种新型处理类型正越来越多地成为我们所处游戏的一部分,而英特尔和 IBM——以及我知道的其他人——似乎已经知道了这一点。

 

作者:Mark Funk

编译:与非网