(二十一)Hyper Threading 和 SIMD 加速矩阵乘法


一、Hyper Threading 超线程技术

      流水线架构、分支预测、乱序执行、超标量和超长指令字这些技术,都是通过指令级别的并行来提高CPU运行的速度,并且在一个引用程序内都需要处理指令依赖的问题。而计算机上是同时运行着多个进程,不同程序之间的指令不存在依赖关系,因此如果不同程序的指令能够“同时”在一个CPU核心上运行是不需要处理指令依赖问题的。

      超线程的CPU能够把一个无力层面的CPU核心伪装成两个逻辑CPU核心,它通过增加很多电路,使得一个CPU核心能够同时维护两个线程的指令状态信息:

      如图所示:COU中增加了一些维护线程指令状态的寄存器,但是其他组件并没有增加,这种架构下通过很小的代价,实现了单个CPU核心可以同时运行两个线程的效果,但是,运算单元并没有增加,因此只有在一些特定场景下,超线程技术才能体现出它的优势,那就是在线程需要等待的场景下,例如数据库访问查询的场景下。

二、SIMD 单指令多数据流

      在使用Python为一个list中每个元素都执行加一操作时有两种运行效率差距很大的方式,一种是使用循环加一,另一种是使用NumPy库的add函数,两者运行效率相差甚至可以达到数十倍:

$ python
>>> import numpy as np
>>> import timeit
>>> a = list(range(1000))
>>> b = np.array(range(1000))
>>> timeit.timeit("[i + 1 for i in a]", setup="from __main__ import a", number=1000000)
32.82800309999993
>>> timeit.timeit("np.add(1, b)", setup="from __main__ import np, b", number=1000000)
0.9787889999997788
>>>

其原因是,NumPy 库使用到了SIMD(单指令多数据流)技术,循环加一操作使用到了SISD(单指令单数据流)技术,而在多核CPU上的运行则使用到了MIMD(多指令多数据流)技术。

SIMD运行速度快的原因是,它的运行中数据的读取和运算都做到了并行,如下图:

  1.  同时从内存中读取四条数据
  2. 四个数据的读取和运算都没有依赖关系
  3. 四个数据的计算并行执行

显然,要使用到SIMD能力,前提是,多数据运算之间没有依赖关系,符合这个要求的场景最典型的就是矩阵计算,如:图形计算、机器学习计算。

三、总结

超线程是一种指令级并行的技术,适用于需要线程等待的场景

SIMD是一种运算级并行的技术,适用于矩阵运算这种同一向量各维度间互不依赖的场景。