gcc 矢量化是什么意思?

bnl4lu3b  于 2023-02-16  发布在  其他
关注(0)|答案(5)|浏览(159)

将代码矢量化是个好主意吗?在何时进行矢量化方面有哪些好的实践?下面会发生什么?

uajslkp6

uajslkp61#

矢量化意味着编译器检测到独立指令可以作为一条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次单个操作。
它提高了性能,但对体系结构提出了更多要求。

pzfprimi

pzfprimi2#

如上所述,向量化用于利用SIMD指令,SIMD指令可以对打包到大型寄存器中的不同数据执行相同的操作。
使编译器能够自动向量化循环的一般准则是确保在循环的不同迭代中没有流依赖性和反依赖性b/w数据元素。
http://en.wikipedia.org/wiki/Data_dependency
有些编译器(如英特尔C++/Fortran编译器)能够自动矢量化代码。如果无法矢量化循环,英特尔编译器能够报告无法执行此操作的原因。这些报告可用于修改代码,使其成为可矢量化代码(假设这是可能的)
相关性在《为现代体系结构优化编译器:基于依赖关系的方法

a8jjtwal

a8jjtwal3#

向量化不需要局限于单个寄存器,因为它可以保存大量数据。就像使用"128"位寄存器保存"4 x 32"位数据一样。它取决于体系结构的限制。有些体系结构具有不同的执行单元,这些执行单元具有自己的寄存器。在这种情况下,部分数据可以馈送到该执行单元,结果可以从与该执行单元对应的寄存器中取出。
例如,考虑以下情况。
对于(i = 0; ii ++)
{
a [i]= a [i]+ b [i];
}
如果我在一个有两个执行单元的架构上工作,那么我的向量大小被定义为2。
对于(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.指针访问可能会产生别名,需要加以防止。

p1iqtdky

p1iqtdky4#

这是SSE代码生成。
您有一个循环,其中包含浮点矩阵代码matrix1[i][j] + matrix2[i][j],编译器生成SSE代码。

llmtgqce

llmtgqce5#

也许还可以看看libSIMDx86(源代码)。
下面是一个很好的例子:
Choosing to Avoid Branches: A Small Altivec Example

相关问题