是否可以使用SIMD指令批处理相同的功能?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以使用SIMD指令批处理相同的功能?相关的知识,希望对你有一定的参考价值。
我有一个场景,许多完全相同的功能(为简单起见,我们只考虑C / C ++和python)将在我的机器上同时执行。直观地说,我只是使用多线程将函数的每个实例视为利用并行性的线程,它们不会争用相同的资源,但是它们会进行许多分支操作(例如,for循环)。但是,由于它们实际上是相同的功能,我正在考虑使用一些SIMD指令(例如AVX-512)对它们进行批处理。当然,它应该是自动的,以便用户不必修改他们的代码。
原因?因为每个线程/进程/容器/ VM占用资源,但AVX只需要一条指令。所以我可以使用相同的硬件来容纳更多用户。
我在网上找到的大多数文章都专注于在函数内部使用AVX指令,例如,加速流数据处理,或处理一些大型计算。他们都没有提到批处理相同功能的不同实例。
我知道存在一些挑战,例如由不同输入引起的不同执行路径,并且将正常功能自动转换为批量版本并不容易,但我认为这在技术上确实是可能的。
这是我的问题
- 是否很难(或可能)将正常功能自动更改为批量版本?
- 如果1为否,那么我应该对该功能施加什么限制才能实现?例如,如果函数只有一条路径而不管数据是什么?
- 还有其他技术可以更好地解决问题吗?我不认为GPU对我来说是一个不错的选择,因为GPU不能支持IO或分支指令,尽管它的SIMT非常适合我的目标。
谢谢!
SSE / AVX基本上是一个向量单元,它允许一次对多个元素的数组进行简单的操作(如+ - * /和,或XOR等)。 AVX1和2具有256字节寄存器,因此您可以执行以下操作: 8个32位单声道,或4个双打。 AVX-512即将推出,但非常罕见。
因此,如果您的函数都是基本类型数组上的所有操作,那么这很自然。如果操作非常简单,使用AVX内在函数重写函数是可行的。复杂的东西(比如不匹配矢量宽度)或甚至在汇编程序中这样做都是一个挑战。
如果你的函数不是在向量上运行那么就变得困难了,而且可能性主要是理论上的。自动向量化编译器有时可以做到这一点,但它很少见且有限,而且非常复杂。
有两种方法可以解决这个问题:矢量化(SIMD)和并行化(线程)。
如果内联函数,GCC已经可以进行所需的SIMD矢量化,并且类型和操作是兼容的(并且它会自动内联小函数而不需要它)。
EG
inline void func (int i) {
somearray[i] = someotherarray[i] * athirdarray[i];
}
for (int i = 0; i < ABIGNUMBER; i++)
func (i);
在-O3
启用了矢量化和内联。
如果函数太复杂,和/或GCC尚未对其进行矢量化,则可以使用OpenMP或OpenACC对其进行并行化。
OpenMP使用特殊标记来告诉编译器在哪里生成线程。
EG
#pragma omp parallel
#pragma omp for
for (int i = 0; i < ABIGNUMBER; i++)
....
是的,你也可以在GPU上做到这一点!您必须进行更多输入才能正确复制和复制数据。只有标记区域在GPU上运行。其他所有东西都在CPU上运行,因此I / O等不是问题。
#pragma omp target map(somearray,someotherarray,athirdarray)
#pragma omp parallel
#pragma omp for
for (int i = 0; i < ABIGNUMBER; i++)
....
OpenACC是一个类似的想法,但更专注于GPU。
您可以在许多地方找到OpenMP和OpenACC编译器。 GCC和LLVM都支持NVidia GPU。 LLVM对AMD GPU有一些支持,也有非官方的GCC版本(很快就会有官方支持)。
以上是关于是否可以使用SIMD指令批处理相同的功能?的主要内容,如果未能解决你的问题,请参考以下文章