OpenMP每次都会给出不同的结果

问题描述 投票:1回答:1
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define KE 10
#define NSTEPS 100
main()
{
    float ex[KE],hy[KE];
    float bn[NSTEPS];
    int n,k,kc,ke;
    float ddx,dt,T;
    float t0,spread,pulse;
    omp_set_num_threads(4);
    kc = KE/2;
    t0 = 40.0;
    spread = 12;
    T = 0;
    FILE * temp = fopen("Exserial.txt", "w");
    /* Initialize */
    for ( k=0; k <= KE; k++ )
    {
        ex[k] = 0.0;
        hy[k] = 0.0;
    }
    double strt=omp_get_wtime();
#pragma omp parallel shared(ex,hy,bn) private(n,k,T,pulse,t0,spread)
    {
        for ( n=1; n<=NSTEPS ; n++) {
            T = T + 1;
            pulse = exp(-.5*(pow( (t0-T)/spread,2.0) ));
            ex[kc] = pulse;
    /* Main FDTD Loop */
    /* Calculate the Ex field */
#pragma omp critical
            {
#pragma omp for 
                for ( k=1; k < KE; k++ )
                { 
#pragma omp atomic update
                    ex[k] = ex[k] + .5*( hy[k-1] - hy[k] ) ;
                    bn[n]=ex[100];
                }
    /* Calculate the Hy field */
#pragma omp for
                for ( k=0; k < KE-1; k++ )
                {
#pragma omp atomic update
                    hy[k] = hy[k] + .5*( ex[k] - ex[k+1] ) ;
                }
            }
        }
    }
    double end=omp_get_wtime();
    printf( "------------------%f\n",end-strt);
    /* End of the Main FDTD Loop */
    /* At the end of the calculation, print out the Ex and Hy fields */
    for ( k=1; k <=KE; k++ )
    { 
        fprintf(temp, "%f\n",ex[k]);
        printf( "%f\n",ex[k]);
    }
}

并行输出(使用的线程数= 4)

 ------------------0.013850
    0.030408
    -0.130364
    0.107690
    0.061082
    0.023526
    0.066983
    -0.030821
    -0.024117
    0.037548
    0.000000

串行输出

-0.013813
-0.028405
-0.044722
-0.064258
-0.087550
-0.072226
-0.062273
-0.055638
-0.052620
0.000000

我不知道我在哪里犯错,但是我在并行程序中得到了不同的结果。每次给出不同的输出。还有一个问题,即当我从顶部删除#pragma omp parallel时,我得到了正确的值,但没有时间优势。我必须添加#pragma omp parallel因此需要一些解决方案。

c multithreading parallel-processing openmp reduction
1个回答
0
投票

按照@ 1201ProgramAlarm的建议,您正在进行一次数据竞赛。它在并行区域内和关键部分外包含以下语句:

            ex[kc] = pulse;

每个线程在每次迭代时都会执行该操作,并且每个线程也会读回该值。读取位于关键部分内并不能将其保存为数据竞赛-写操作也必须也位于关键部分(不一定是同一部分),否则将受到某种形式的同步保护,以避免数据竞赛。

但是这里的问题是如此之大,以至于数据争用几乎是无关紧要的。 main问题是循环迭代之间的计算具有很强的数据依赖性。也就是说,当串行运行时,外循环的每次迭代都会根据前一次迭代中计算出的值来更新exhy的所有元素。无论您进行多少同步或进行多大的关键处理,如果您允许外循环迭代以并行的方式执行,那么您就无法期望得到相同的结果(甚至一致的结果)。] >

这里的一线希望是,并行化无论如何也不会给您带来什么好处,因为外循环执行的几乎所有工作都在关键部分。仅删除omp parallelomp critical指令对改进此代码将有很长的路要走。对于这么小的KE和如此简单的计算,也可以不留内部的omp for,也没有多大意义,但是如果KE很大,那么您可以考虑保留的并行化。内部循环。

© www.soinside.com 2019 - 2024. All rights reserved.