【发布时间】:2014-04-25 23:28:59
【问题描述】:
我对以下循环进行了矢量化,该循环出现在我正在开发的应用程序中:
void vecScl(Node** A, Node* B, long val){
int fact = round( dot / const);
for(i=0; i<SIZE ;i++)
(*A)->vector[i] -= fact * B->vector[i];
}
这是 SSE 代码:
void vecSclSSE(Node** A, Node* B, long val){
int fact = round( dot / const);
__m128i vecPi, vecQi, vecCi, vecQCi, vecResi;
int sseBound = SIZE/4;
for(i=0,j=0; j<sseBound ; i+=4,j++){
vecPi = _mm_loadu_si128((__m128i *)&((*A)->vector)[i] );
vecQi = _mm_set_epi32(fact,fact,fact,fact);
vecCi = _mm_loadu_si128((__m128i *)&((B)->vector)[i] );
vecQCi = _mm_mullo_epi32(vecQi,vecCi);
vecResi = _mm_sub_epi32(vecPi,vecQCi);
_mm_storeu_si128((__m128i *) (((*A)->vector) + i), vecResi );
}
//Compute remaining positions if SIZE % 4 != 0
for(; i<SIZE ;i++)
(*A)->vector[i] -= q * B->vector[i];
}
虽然这在正确性方面有效,但使用和不使用 SSE 的性能完全相同。我正在编译代码:
g++ *.cpp *.h -msse4.1 -march=corei7-avx -mtune=corei7-avx -mno-avx -mno-aes -Warray-bounds -O2
这是因为我没有分配(并相应地使用 SSE 函数)对齐的内存吗?代码更改起来非常复杂,所以我暂时避免这样做。
顺便说一句,在进一步改进方面,考虑到我受限于 Sandy Bridge 架构,我能做的最好的事情是什么?
编辑:编译器尚未对代码进行矢量化。首先,我将向量的数据类型更改为shorts,这不会改变性能。然后,我用-fno-tree-vectorize编译,性能是一样的。
非常感谢
【问题讨论】:
-
可能编译器已经对代码进行了向量化,检查asm代码。
-
我不能,我正在编译多个 .c 和 .cpp 文件。显然,当您只编译一个文件时它工作正常。我也确信它没有对代码进行向量化,因为如果我将数据类型更改为 short(而不是 int),性能必然会更好,但事实并非如此。
-
我不太了解如何编写矢量化代码,但我知道对齐是至关重要的。输入数组需要对齐到更大的尺寸,(我猜)可以使用属性来表达。
-
@a3mlord 您可以在任何现代 IDE 中检查任何文件、任何函数甚至表达式的反汇编。如果没有编译器生成的代码,就没什么好讨论的了。为什么你认为短裤“一定会更好”?您如何描述绩效?
-
@leemes:对齐对于最近的 Intel CPU(Ivy Bridge、Sandy Bridge、Haswell 等)来说并不是很重要。不过,它仍然可以产生很小的影响。
标签: c++ performance vectorization sse