我的代码中有几个嵌套的for循环,我尝试在intel i7内核上使用intel SSE指令来加速应用程序。
代码结构如下(val在较高的for循环中设置):
_m128 in1,in2,tmp1,tmp2,out;
float arr[4] __attribute__ ((aligned(16)));
val = ...;
... several higher for loops ...
for(f=0; f<=fend; f=f+4){
index2 = ...;
for(i=0; i<iend; i++){
for(j=0; j<jend; j++){
inputval = ...;
index = ...;
if(f<fend-4){
arr[0] = array[index];
arr[1] = array[index+val];
arr[2] = array[index+2*val];
arr[3] = array[index+3*val];
in1 = _mm_load_ps(arr);
in2 = _mm_set_ps1(inputval);
tmp1 = _mm_mul_ps(in1, in2);
tmp2 = _mm_loadu_ps(&array2[index2]);
out = _mm_add_ps(tmp1,tmp2);
_mm_storeu_ps(&array2[index2], out);
} else {
//if no 4 values available for SSE instruction execution execute serial code
for(int u = 0; u < fend-f; u++ ) array2[index2+u] += array[index+u*val] * inputval;
}
}
}
}
我认为有两个主要问题:用于对齐“数组”中的值的缓冲区,以及当不剩4个值时(例如,当fend = 6时,剩下两个值的事实,应使用顺序代码执行) )。还有其他方法可以从in1加载值和/或以3或2个值执行SSE指令吗?
到目前为止,感谢您的回答。加载与我想的一样好,但是在else语句中的“剩余”部分是否可以使用SSE指令解决?
最佳答案
我认为更大的问题是,如此大量的数据移动所需的计算量很少:
arr[0] = array[index]; // Data Movement
arr[1] = array[index+val]; // Data Movement
arr[2] = array[index+2*val]; // Data Movement
arr[3] = array[index+3*val]; // Data Movement
in1 = _mm_load_ps(arr); // Data Movement
in2 = _mm_set_ps1(inputval); // Data Movement
tmp1 = _mm_mul_ps(in1, in2); // Computation
tmp2 = _mm_loadu_ps(&array2[index2]); // Data Movement
out = _mm_add_ps(tmp1,tmp2); // Computation
_mm_storeu_ps(&array2[index2], out); // Data Movement
虽然“可能”可以简化此过程。我完全不相信矢量化在这种情况下将完全有益。
您必须更改数据布局,以避免出现跨越式访问
index + n*val
。或者,您可以等到AVX2收集/散布说明在2013年可用之前?
关于c++ - 嵌套for循环内的SSE指令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8383547/