-1

我正在尝试使用 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;
            }
            .
            .
            .
       }
4

2 回答 2

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];
}    
于 2013-09-09T21:50:07.640 回答
0

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

于 2013-09-09T19:56:46.977 回答