矢量化是什么意思?

向量化代码是一个好主意吗? 在什么时候这样做有什么好的做法? 下面会发生什么?

向量化意味着编译器检测到您的独立指令可以作为一条SIMD指令执行。 通常的例子是,如果你做了类似的事情

for(i=0; i 

它将被矢量化为(使用矢量符号)

 for (i=0; i<(NN%VF); i+=VF){ a[i:i+VF] = a[i:i+VF] + b[i:i+VF]; } 

基本上,编译器选择一个可以同时在arrays的VF元素上完成的操作,并执行N / VF次,而不是单次操作N次。

它提高了性能,但对架构提出了更高的要求。

如上所述,矢量化用于利用SIMD指令,SIMD指令可以执行打包到大寄存器中的不同数据的相同操作。

使编译器能够自动向量化循环的通用准则是确保循环的不同迭代中没有流和反依赖性的b / w数据元素。

http://en.wikipedia.org/wiki/Data_dependency

像英特尔C ++ / Fortran编译器这样的编译器能够自动生成代码。 如果它无法对循环进行矢量化,英特尔编译器就能够报告为什么它不能这样做。 有报告可用于修改代码,使其变得可矢量化(假设它是可能的)

“为现代架构优化编译器:基于依赖的方法”一书中深入介绍了依赖关系

这是SSE代码生成。

你有一个带有浮点矩阵代码的循环:matrix1 [i] [j] + matrix2 [i] [j],编译器生成SSE代码。

矢量化不必限于可以容纳大数据的单个寄存器。 就像使用’128’位寄存器来保存’4 x 32’位数据一样。 这取决于架构限制。 某些体系结构具有不同的执行单元,这些执 在这种情况下,可以将一部分数据馈送到该执行单元,并且可以从对应于该执行单元的寄存器获取结果。

例如,考虑以下情况。

for(i = 0; i {
a [i] = a [i] + b [i];
}

如果我正在开发一个有两个执行单元的架构,那么我的矢量大小定义为两个。 上面提到的循环将被重新定义为

for(i = 0; i <(N / 2); i + = 2)
{
a [i] = a [i] + b [i];

a [i + 1] = a [i + 1] + b [i + 1];
}

注意:for语句中的2是从向量大小派生的。

由于我有两个执行单元,循环内的两个语句将被送入两个执行单元。 总和将分别累积在执行单元中。 最后,将执行累计值的总和(来自两个执行单元)。

好的做法是
1.在向量化循环之前,需要检查依赖性(在循环的不同迭代之间)之类的约束。
2.需要防止函数调用。
3.指针访问可以创建别名,需要防止它。

也许还看看libSIMDx86(源代码)。

一个很好的例子很好地解释了:

选择避免分支:小Altivec示例