OpenMP:并行程序不是更快(或不是非常快)然后串行.我究竟做错了什么?

Rob*_*tex 1 c performance gcc openmp

看看这段代码:

#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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,结果:

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
Run Code Online (Sandbox Code Playgroud)

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

我使用OS Ubuntu在几台计算机(工作中的Intel Core i5,家中的Intel Core2Duo T7500)上测试了它,并且总是得到相同的结果:OpenMP不会显着提高性能.

我还测试了维基百科的例子并获得了相同的结果.

Mys*_*ial 17

您的代码中存在两个问题:

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

首先,您需要parallel实际并行运行OpenMP:

#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)

其次,你j在平行区域之外宣布.这将使它在所有线程之间共享.所以所有线程都在并行区域内读取和修改它.

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

你需要做的是j为每个线程制作本地.这可以通过以下任一方式完成:

  1. j在并行区域内声明.
  2. 或者添加private(j)到pragma :( #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;
}
Run Code Online (Sandbox Code Playgroud)
No OpenMP:            6.433378
OpenMP with global j: 9.634591
OpenMP with local j:  2.266667
Run Code Online (Sandbox Code Playgroud)

  • +1.另外:`#pragma omp parallel for private(j)`可以工作,而不是在本地范围内声明`j`. (2认同)