OpenMP paralelization抑制矢量化

时间:2016-11-16 12:09:53

标签: c++ openmp vectorization

我是OpenMP的新手,我正在尝试使用OpenMP对代码进行并行化:

#pragma omp parallel for
for(int k=0;k<m;k++)
{
   for(int j=n-1;j>=0;j--)
   {
       outX[k+j*m] = inB2[j+n * k] / inA2[j*n + j];

       for(int i=0;i<j;i++)
       {
           inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j];
       }
   }
}

对外循环进行并行化是非常简单的,但为了优化它,我想要对最内循环(对i迭代的循环)进行并行化。但是,当我尝试这样做时:

#pragma omp parallel for
for(int i=0;i<j;i++)
{
    inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j];
}

编译器不会对内部循环进行矢量化(“因为可能的别名而导致为矢量化而循环”),这使得它运行得更慢。我使用gcc -ffast-math -std=c++11 -fopenmp -O3 -msse2 -funroll-loops -g -fopt-info-vec prog.cpp

编译了它

感谢您的任何建议!

编辑:我正在为数组使用__restrict关键字。

EDIT2:有趣的是,当我在内循环中仅保留pragma并将其从外部移除时,gcc将向量化它。因此,当我尝试对两个周期进行并列化时,问题才会发生。

EDIT3:当我使用#pragma omp parallel for simd时,编译器将向量化循环。但它仍然比没有内部循环并行化更慢。

3 个答案:

答案 0 :(得分:1)

我的猜测是,在你内部循环并行化后,你的编译器失去了inA2inB2outX的轨道。默认情况下,它假定任何指针指向的任何内存区域可能彼此重叠。在C语言中,C99标准引入了restrict关键字,该关键字通知编译器指针指向一个未被任何其他指针指向的内存块。 C ++没有这样的关键字,但幸运的是,g++具有适当的扩展名。因此,尝试将__restrict添加到循环触及的指针的声明中。例如,替换

double* outX;

double* __restrict outX;

答案 1 :(得分:1)

您是否尝试过首先使内环旋转?然后添加并行部分(这可能会导致性能降低,具体取决于缓存未命中)

AndroidSchedulers

总是需要一些时间让#pragma使用共享,公共等等...而且我没有对此进行测试。

答案 2 :(得分:1)

谢谢大家的回答。我设法使用#pragma omp parallel for simd来矢量化内部循环,但程序比没有并行化时慢。我最终找到了一个稍微不同的算法来解决问题,这要快得多。 谢谢你的帮助!