将代码矢量化是个好主意吗?在何时做这件事方面有哪些好的实践?下面发生了什么?
发布于 2009-10-04 15:18:00
向量化意味着编译器检测到您的独立指令可以作为一条SIMD指令执行。通常的例子是,如果你做像这样的事情
for(i=0; i<N; i++){
a[i] = a[i] + b[i];
}它将被矢量化为(使用向量符号)
for (i=0; i<(N-N%VF); i+=VF){
a[i:i+VF] = a[i:i+VF] + b[i:i+VF];
}基本上,编译器选择一个可以同时在数组的VF元素上执行的操作,并执行N/VF次,而不是执行N次单一操作。
它提高了性能,但对体系结构提出了更多要求。
发布于 2009-10-09 20:17:58
如上所述,矢量化用于利用SIMD指令,SIMD指令可以对打包到大寄存器中的不同数据执行相同的操作。
使编译器能够自动向量化循环的一般原则是确保在循环的不同迭代中没有流和反依赖b/w数据元素。
http://en.wikipedia.org/wiki/Data_dependency
某些编译器,如英特尔C++/Fortran编译器,能够自动向量化代码。如果无法对循环进行矢量化,英特尔编译器能够报告无法进行矢量化的原因。有一些报告可以用来修改代码,使其变得可向量化(假设这是可能的)
“优化现代架构的编译器:一种基于依赖的方法”一书对依赖进行了深入的讨论。
发布于 2009-11-04 20:06:13
向量化不需要局限于可以保存大量数据的单个寄存器。例如使用'128‘位寄存器来保存'4 x 32’位数据。这取决于体系结构的限制。一些体系结构具有不同执行单元,这些执行单元具有它们自己的寄存器。在这种情况下,可以将一部分数据馈送到该执行单元,并且可以从对应于该执行单元的寄存器获取结果。
例如,考虑下面的情况。
(i=0;I< N;i++)的
{
ai = ai + bi;
}
如果我在一个有两个执行单元的架构上工作,那么我的向量大小被定义为两个。上面提到的循环将被重新构造为
(i=0;i<(N/2);i+=2)
{
ai = ai + bi;ai+1 =ai+ bi+1;
}
注意: for语句中的2是从向量大小派生而来的。
因为我有两个执行单元,所以循环中的两个语句将被提供给这两个执行单元。总和将分别在执行单元中累加。最后,将执行累加值的和(来自两个执行单元)。
好的实践是
在向量化循环之前,需要检查像依赖项这样的约束(循环的不同迭代之间)。prevented.
https://stackoverflow.com/questions/1516622
复制相似问题