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

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

我不认为你的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];
}    

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

链接地址: http://www.djcxy.com/p/79231.html

上一篇: Why my C code is slower using OpenMP

下一篇: OpenMP parallelize multiple sequential loops