我有一个基本的计算函数,我应用于数组中的每个项目。这个函数做的不仅仅是对两个向量求和。
我想使用SIMD命令并行处理数组中的多个项目。
我发现这些示例对我的情况来说太简单了(它们不包括函数调用): http://www.doc.ic.ac.uk/~nloriant/files/scfpsc-pc.pdf
我尝试使用数组表示法,如下所示: http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/cpp/mac/optaps/common/optaps_elem_functions.htm
但这并没有加速我的代码。我不明白我做错了什么,如果我需要更加类似汇编的SIMD风格,我该如何在那里引入函数调用......
如果有人可以帮助我,或者根据我的需要向我推荐一个好的来源,那我就非常有用。
谢谢!!!!
代码示例:
这是应用于数组中每个项目的基本功能:
float VarFlow::gauss_seidel_step(IplImage* u, int i, float h, float J11, float J12, float J13, float vi){
int x = i%u->width;
int y = i/u->width;
int start_y, end_y, start_x, end_x;
int N_num = 0;
start_y = y - 1;
end_y = y + 1;
start_x = x - 1;
end_x = x+1;
float temp_u = 0;
// Sum top neighbor
if(start_y > -1){
temp_u += *((float*)(u->imageData + start_y*u->widthStep) + x);
N_num++;
}
// Sum bottom neighbor
if(end_y < u->height){
temp_u += *((float*)(u->imageData + end_y*u->widthStep) + x);
N_num++;
}
// Sum left neighbor
if(start_x > -1){
temp_u += *((float*)(u->imageData + y*u->widthStep) + start_x);
N_num++;
}
// Sum right neighbor
if(end_x < u->width){
temp_u += *((float*)(u->imageData + y*u->widthStep) + end_x);
N_num++;
}
temp_u = temp_u - (h*h/alpha)*(J12*vi + J13);
temp_u = temp_u / (N_num + (h*h/alpha)*J11);
return temp_u;
}
我想用__declspec(vector)声明它并像这样调用它:
u_ptr[0:max_i:1] = gauss_seidel_step(imgU, vect[0:max_i:1], h, fxfx_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fxft_ptr[0:max_i:1], v_ptr[0:max_i:1]);
v_ptr[0:max_i:1] = gauss_seidel_step(imgV, vect[0:max_i:1], h, fyfy_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fyft_ptr[0:max_i:1], u_ptr[0:max_i:1]);
而不是for循环。
我很乐意为此提供方向(可能是类似示例的链接),但不是完整解决方案。
谢谢!
答案 0 :(得分:3)
SIMD和条件分支不能很好地混合。
将条件语句转换为布尔掩码和乘法。这会让你走向正确的路径来进行矢量化操作。
e.g。
if(end_x < u->width){
temp_u += value;
N_num++;
}
变为
ltmask = (end_x < u->width); // see _mm_cmplt_ps
temp_u += ltmask*value; // see _mm_add_ps, _mm_and_ps
N_num += ltmask; // use _mm_and_ps with a vector of 1.0f