原始代码看起来像
for(i=0;i<20;i++){
if(){
do();
}
else{
num2 = _mm_set_pd(Phasor.imaginary, Phasor.real);
for(int k=0; k<SamplesIneachPeriodCeil[iterationIndex]; k++)
{
/*SamplesIneachPeriodCeil[iterationIndex] is in range of 175000*/
num1 = _mm_loaddup_pd(&OutSymbol[k].real);
num3 = _mm_mul_pd(num2, num1);
num1 = _mm_loaddup_pd(&OutSymbol[k].imaginary);
num2 = _mm_shuffle_pd(num2, num2, 1);
num4 = _mm_mul_pd(num2, num1);
num3 = _mm_addsub_pd(num3, num4);
num2 = _mm_shuffle_pd(num2, num2, 1);
num5 = _mm_set_pd(InSymbolInt8[k],InSymbolInt8[k] );
num6 = _mm_mul_pd(num3, num5);
num7 = _mm_set_pd(Out[k].imaginary,Out[k].real);
num8 = _mm_add_pd(num7,num6);
_mm_storeu_pd((double *)&Out[k], num8);
}
Out = Out + SamplesIneachPeriodCeil[iterationIndex];
}
}
这段代码给了我15milsec的速度
当我修改代码以将openmp包含为
时注意::这里我只包括其他部分
else{
int size = SamplesIneachPeriodCeil[iterationIndex];
#pragma omp parallel num_threads(2) shared(size)
{
int start,end,tindex,tno,no_of_iteration;
tindex = omp_get_thread_num();
tno = omp_get_num_threads();
start = tindex * size / tno;
end = (1+ tindex)* size / tno ;
num2 = _mm_set_pd(Phasor.imaginary, Phasor.real);
int k;
for(k = start ; k < end; k++){
num1 = _mm_loaddup_pd(&OutSymbol[k].real);
num3 = _mm_mul_pd(num2, num1);
num1 = _mm_loaddup_pd(&OutSymbol[k].imaginary);
num2 = _mm_shuffle_pd(num2, num2, 1);
num4 = _mm_mul_pd(num2, num1);
num3 = _mm_addsub_pd(num3, num4);
//_mm_storeu_pd((double *)&newSymbol, num3);
num2 = _mm_shuffle_pd(num2, num2, 1);
num5 = _mm_set_pd(InSymbolInt8[k],InSymbolInt8[k] );
num6 = _mm_mul_pd(num3, num5);
num7 = _mm_set_pd(Out[k].imaginary,Out[k].real);
num8 = _mm_add_pd(num7,num6);
_mm_storeu_pd((double *)&Out[k], num8);
}
}
Out = Out + size;
}
此代码显示的速度是30万毫秒
所以我想知道我在这里做错了什么。
答案 0 :(得分:2)
你没有做任何事情来分配两个线程之间的循环执行。您只是创建一个具有两个线程的并行区域,这些线程执行完全相同的代码。您可能想要做的是将并行区域移动到仅包含 for
循环并使用工作共享构造:
int k;
#pragma omp parallel for num_threads(2) ...
for(k = start ; k < end; k++){
...
}
击> <击> 撞击>
感谢都铎的纠正。您的代码已正确并行化,但在循环内部有一个并行区域。进入和退出并行区域与一些开销相关联。通常这被描述为“fork / join model”,其中在进入该区域时创建一组线程,然后在退出时将所有线程连接到master。大多数OpenMP运行时使用各种线程池技术来减少开销,但它仍然存在。
你的循环运行15毫秒。与OpenMP开销相比,这已经足够快,因此开销变得可见。考虑在外环上移动并行区域,开销应减少最多20倍(取决于else
分支的使用频率),但您可能仍然看不到计算时间的改善
并行化仅适用于问题足够大的程序,因此与计算时间相比,通信或同步开销可以忽略不计或至少很小。
答案 1 :(得分:0)
您应该在外部循环之外(i
之外)开始并行区域,并使用k
将for循环并行化omp for
。循环中使用的所有变量(num1
,num2
...)最好只在其中声明,以便它们自动private
(实际上,大多数变量可以重复使用,但是编译器应该发现我们无论如何。)