1

看看这段代码:

#include <stdio.h>
#include <omp.h>

int main()
{
    long i, j;

    #pragma omp for
    for(i=0;i<=100000;i++)
    {
        for(j=0;j<=100000;j++)
        {
            if((i ^ j) == 5687)
            {
                //printf("%ld ^ %ld\n", i, j);
                break;
            }
        }
    }
}

所以,结果:

robotex@robotex-work:~/Projects$ gcc test.c -fopenmp -o test_openmp
robotex@robotex-work:~/Projects$ gcc test.c -o test_noopenmp
robotex@robotex-work:~/Projects$ time ./test_openmp
real    0m11.785s
user    0m11.613s
sys 0m0.008s
robotex@robotex-work:~/Projects$ time ./test_noopenmp

real    0m13.364s
user    0m13.253s
sys 0m0.008s
robotex@robotex-work:~/Projects$ time ./test_noopenmp

real    0m11.955s
user    0m11.853s
sys 0m0.004s
robotex@robotex-work:~/Projects$ time ./test_openmp

real    0m15.048s
user    0m14.949s
sys 0m0.004s

怎么了?为什么 OpenMP 程序较慢?我该如何纠正?

我用操作系统 Ubuntu 在几台计算机(工作中的 Intel Core i5,家庭中的 Intel Core2Duo T7500)上对其进行了测试,并且始终得到相同的结果:OpenMP 并没有显着提高性能。

我还测试了来自 Wikipedia 的示例并得到了相同的结果。

4

1 回答 1

17

您的代码中有两个问题:

  1. parallel在你的杂注中错过了。所以它只使用1个线程。
  2. 您有一个竞争条件,j因为它是在并行区域之外声明的。

首先,您需要parallel真正让 OpenMP 并行运行:

#pragma omp parallel for

其次,您j在并行区域之外声明。这将使它在所有线程之间共享。所以所有线程都在并行区域内读取和修改它。

因此,您不仅有竞争条件,而且由所有失效引起的缓存一致性流量正在扼杀您的性能。

您需要做的是使j每个线程本地化。这可以通过以下任一方式完成:

  1. j在并行区域内声明。
  2. 或添加private(j)到编译指示:(#pragma omp parallel for private(j)
    正如@ArjunShankar 在评论中指出的那样)

试试这个:

int main()
{
    double start = omp_get_wtime();

    long i;

#pragma omp parallel for
    for(i=0;i<=100000;i++)
    {
        long j;
        for(j=0;j<=100000;j++)
        {
            if((i ^ j) == 5687)
            {
                //printf("%ld ^ %ld\n", i, j);
                break;
            }
        }
    }

    double end = omp_get_wtime();

    printf("%f\n",end - start);
    return 0;
}

No OpenMP:            6.433378
OpenMP with global j: 9.634591
OpenMP with local j:  2.266667
于 2012-04-10T16:21:04.450 回答