为什么我的C代码使用OpenMP更慢

时间:2013-09-09 18:21:18

标签: c++ multithreading parallel-processing openmp pragma

我正在尝试使用OpenMP在CPU上进行多线程编程。我有很多for循环,它们很适合并行。我在这里附上了我的部分代码。当我第一次使用#pragma omp parallel进行缩减时,我的代码更快,但是当我尝试使用相同的命令来并行化其他循环时,它变得更慢。有没有人知道为什么会这样?

.
.
.

        omp_set_dynamic(0);
        omp_set_num_threads(4);

        float *h1=new float[nvi];
        float *h2=new float[npi];

        while(tol>0.001)
        {
            std::fill_n(h2, npi, 0);
            int k,i;
            float h222=0;
            #pragma omp parallel for private(i,k) reduction (+: h222)

            for (i=0;i<npi;++i)
            {   
                int p1=ppi[i];
            int m = frombus[p1];
                for (k=0;k<N;++k)
                {
                h222 +=  v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k]) 
                             + B[m-1][k]*sin(del[m-1]-del[k]));
                }
                h2[i]=h222;
            }

            //*********** h3*****************

            std::fill_n(h3, nqi, 0);
            float h333=0;

            #pragma omp parallel for private(i,k) reduction (+: h333) 

            for (int i=0;i<nqi;++i)
            {    
            int q1=qi[i];
            int m = frombus[q1];
                for (int k=0;k<N;++k)
                {
                    h333 += v[m-1]*v[k]*(G[m-1][k]*sin(del[m-1]-del[k]) 
                            - B[m-1][k]*cos(del[m-1]-del[k]));
                } 
                h3[i]=h333;
            }
            .
            .
            .
       }

2 个答案:

答案 0 :(得分:1)

我认为您的OpenMP代码与没有OpenMP的结果相同。我们只关注代码的h2[i]部分(因为h3[i]具有相同的逻辑)。 h2[i]对索引i存在依赖关系(即h2 [1] = h2 [1] + h2 [0])。您正在进行的OpenMP减少将无法给出正确的结果。 如果你想使用OpenMP进行缩减,你需要在内循环上进行这样的修改:

float h222 = 0;
for (int i=0; i<npi; ++i) {
    int p1=ppi[i];
    int m = frombus[p1];        
    #pragma omp parallel for reduction(+:h222)
    for (int k=0;k<N; ++k) {
        h222 +=  v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k]) 
                         + B[m-1][k]*sin(del[m-1]-del[k]));
    }
    h2[i] = h222;
}

但是,我不知道这是否会非常有效。 另一种方法是在外部循环上并行填充h2[i]而不进行减少,然后在串行中处理依赖关系。即使串行循环未并行化,它仍然应该有一个小的对计算时间的影响,因为它没有k的内部循环。这应该在有和没有OpenMP的情况下给出相同的结果,并且仍然很快。

#pragma omp parallel for
for (int i=0; i<npi; ++i) {
    int p1=ppi[i];
    int m = frombus[p1];
    float h222 = 0;
    for (int k=0;k<N; ++k) {
        h222 +=  v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k]) 
                         + B[m-1][k]*sin(del[m-1]-del[k]));
    }
    h2[i] = h222;
}
//take care of the dependency serially
for(int i=1; i<npi; i++) {
    h2[i] += h2[i-1];
}    

答案 1 :(得分:0)

请记住,创建和销毁线程是一个耗时的过程;计算流程的执行时间并亲自查看。您只使用两次并行缩减,这可能比串行缩减快,但创建线程的初始成本可能仍然更高。尝试并行化最外层循环(如果可能)以查看是否可以获得加速。