使用OpenMP并行化嵌套循环

时间:2018-11-07 14:38:16

标签: c openmp

我尝试使用OpenMP并行化嵌套循环,但是我不确定这是否是正确的方法。 这是代码中具有嵌套循环的部分。这只是一个通用代码。 我给noofrecords作为50k,即使并行化也要花费很多时间。有人可以提出更好的主意来并行化代码吗? 我只是在下面的代码中并行化外循环。

int ctd=0;
#pragma omp parallel for default(none), private(j,k,l), shared(A,B,C,D,ctd)
for(int j=0; j <noofrecords; j++)
{
    for( int k=0; k<noofrecords; k++)
    {
        for( int l=0; l<noofrecords; l++)
        {
            if(condition)
            {
D[ctd].a1=A[i].a1;
ctd++;
              }}}}

2 个答案:

答案 0 :(得分:1)

您可以使用折叠子句,在这种情况下,您有3个连续的for循环,因此它类似于: #pragma omp为默认值(无),私有(j,k,l),共享(A,B,C,D,ctd)并行收起(3)

如果for循环是连续的并且代码在最内层的循环中(在您发布的代码中就是这种情况),它将起作用。它的noofrecords比您的最大线程数大得多,加速不会令人印象深刻。如果即使并行运行也很慢,则可能意味着瓶颈不是您的处理能力(很可能是内存已经100%工作了)。

此外,我不确定您是否真的想要私有(j,k,l)...

答案 1 :(得分:0)

  1. 创建类型为a1的{​​{1}}的临时数组,其元素数量等于预期的D.a1的最大值。
  2. 为每个线程创建ctd的临时数组a2
  3. 并行填充a1并使用a2计算a2的大小
  4. ctd2开始依次填充数组a1并将a2添加到ctd2
  5. 从a1并行写入D.a1

类似这样的东西

ctd

int ctd=0; double *a1 = malloc(sizeof *a1 * N); //Step 1 #pragma omp parallel { int ctd2 = 0; double *a2 = malloc(sizeof *a2 * N); //step 2 #pragma omp for nowait for(int j=0; j<noofrecords; j++) for(int k=0; k<noofrecords; k++) for(int l=0; l<noofrecords; l++) if(condition) a2[ctd2++] = A[i].a1; //step 3 #pragma omp for schedule(static) ordered for(int i=0; i<omp_get_num_threads(); i++) #pragma omp ordered memcpy(&a1[ctd], a2, sizeof *a1 * ctd2), ctd += ctd2; //step 4 #pragma omp for for(int j=0; j<ctd; j++) D[j].a1 = a1[j]; // step 5 free(a2); } free(a1); 应该是您希望ctd拥有的最大大小。此方法的一个内存效率低下是,N的大小也a2被分配了,该大小可能太大。像C ++中的N或glib中的std::vector这样的动态向量将提高内存效率。