所以我在使用openmp找出并行化这些for循环的最佳方法时遇到了一些麻烦。我猜测最大的加速可能来自中间循环的并行化,就像我在这里做的那样:
for(i = 0; i < m/16*16; i+=16){
#pragma omp parallel for
for(j = 0; j < m; j++){
C_column_start = C+i+j*m;
c_1 = _mm_loadu_ps(C_column_start);
c_2 = _mm_loadu_ps(C_column_start+4);
c_3 = _mm_loadu_ps(C_column_start+8);
c_4 = _mm_loadu_ps(C_column_start+12);
for (k=0; k < n; k+=2){
A_column_start = A+k*m;
a_1 = _mm_loadu_ps(A_column_start+i);
a_2 = _mm_loadu_ps(A_column_start+i+4);
a_3 = _mm_loadu_ps(A_column_start+i+8);
a_4 = _mm_loadu_ps(A_column_start+i+12);
b_1 = _mm_load1_ps(A_column_start+j);
mul_1 = _mm_mul_ps(a_1, b_1);
mul_2 = _mm_mul_ps(a_2, b_1);
mul_3 = _mm_mul_ps(a_3, b_1);
mul_4 = _mm_mul_ps(a_4, b_1);
c_4 = _mm_add_ps(c_4, mul_4);
c_3 = _mm_add_ps(c_3, mul_3);
c_2 = _mm_add_ps(c_2, mul_2);
c_1 = _mm_add_ps(c_1, mul_1);
A_column_start+=m;
a_1 = _mm_loadu_ps(A_column_start+i);
a_2 = _mm_loadu_ps(A_column_start+i+4);
a_3 = _mm_loadu_ps(A_column_start+i+8);
a_4 = _mm_loadu_ps(A_column_start+i+12);
b_1 = _mm_load1_ps(A_column_start+j);
mul_1 = _mm_mul_ps(a_1, b_1);
mul_2 = _mm_mul_ps(a_2, b_1);
mul_3 = _mm_mul_ps(a_3, b_1);
mul_4 = _mm_mul_ps(a_4, b_1);
c_4 = _mm_add_ps(c_4, mul_4);
c_3 = _mm_add_ps(c_3, mul_3);
c_2 = _mm_add_ps(c_2, mul_2);
c_1 = _mm_add_ps(c_1, mul_1);
}
_mm_storeu_ps(C_column_start, c_1);
_mm_storeu_ps(C_column_start+4, c_2);
_mm_storeu_ps(C_column_start+8, c_3);
_mm_storeu_ps(C_column_start+12, c_4);
}
}
然而,这目前几乎没有加速。任何提示都会很棒。我已经被困了一段时间了。
答案 0 :(得分:2)
首先,您确定循环是可并行化的吗?值m
的范围是什么?
当所有三个嵌套循环都可并行化并且m
足够大(比如至少16个左右)时,那么并行化最外层循环将是最有益的。并行化内部循环可能会导致来自omp parallel for
的严重分叉加入。
对于低速加速,这里有一些清单:
omp parallel for
的隐式屏障之外没有同步,因此应该使用所有核心。m
数字是多少?而且,计算长度是多少?如果m
在计算量很小的情况下很大,则由omp parallel for
引起的并行开销可能会抵消并行化的好处。并行化内部循环时,行程计数(例如m
)不应该很大。