为什么openmp并行化这段代码?

时间:2012-06-18 06:10:10

标签: c openmp

此代码不会使代码更快地计算4个和。相反,它甚至需要更多时间。 输出也不是预期的。

#include <stdio.h>
#include <omp.h>
int main()
{
    int i,j,k,l;
    int sum = 0,sum1 = 0,sum2 = 0,sum3 = 0;
    #pragma omp parallel
    {
        #pragma omp sections
        {
            #pragma omp section
            {
                printf("%d",omp_get_thread_num());
                for(i = 0; i < 500000000; i++) sum = sum + 1;
            }
            #pragma omp section
            {
                printf("%d",omp_get_thread_num());
                for(i = 0; i < 500000000; i++) sum1 = sum1 + 1;
            }
            #pragma omp section
            {
                printf("%d",omp_get_thread_num());
                for(i = 0; i < 500000000; i++) sum2 = sum2 + 1;
            }
            #pragma omp section
            {
                printf("%d",omp_get_thread_num());
                for(i = 0; i < 500000000; i++) sum3 = sum3 + 1;
            }
        }
    }
    printf("sum is %d %d %d %d",    sum,sum1,sum2,sum3);
}

输出为sum is 218748707 222052401 239009041 196849489

让我知道在这里使用openmp的缺陷。

2 个答案:

答案 0 :(得分:5)

减速源于sumsum1sum2sum3是共享变量的事实,因此编译器必须生成获取/更新/存储指令每个增量而不是像寄存器一样只保留寄存器中的中间和。

你应该使用它所使用的线程的每个和。最简单的方法是减少每个总和:

#pragma omp parallel private(i) reduction(+:sum,sum1,sum2,sum3)
{
    // Rest of the code goes unchanged
}

private(i)将解决问题,但结果不正确。 reduction(+:sum,sum1,sum2,sum3)会使每个帖子累积自己的sumsum1sum2sum3副本,最后将本地副本添加到表单中最后的价值观。

以下是一些表现数据:

串行版 - 3.812秒:

$ gcc -o mp.x mp.c -lgomp
$ time ./mp.x
0000sum is 500000000 500000000 500000000 500000000
./mp.x  3.81s user 0.00s system 99% cpu 3.812 total

带共享变量的OpenMP版本 - 7.982秒:

$ gcc -fopenmp -o mp.x mp.c
$ time OMP_NUM_THREADS=4 ./mp.x
0132sum is 500000000 500000000 500000000 500000000
OMP_NUM_THREADS=4 ./mp.x  21.88s user 0.86s system 284% cpu 7.982 total

OpenMP版本减少 - 1.226秒:

$ gcc -fopenmp -o mp.x mp.c
$ time OMP_NUM_THREADS=4 ./mp.x
0321sum is 500000000 500000000 500000000 500000000
OMP_NUM_THREADS=4 ./mp.x  4.53s user 0.00s system 370% cpu 1.226 total

另外还有另一个代码转换会降低速度,而sumsum1sum2sum3位于堆栈上主程序,而部分代码由OpenMP处理器提取并放入单独的函数,然后由并行团队中的每个线程调用。该函数提供了一个数据结构,其中包含指向四个共享和的指针,并且代码与这些指针一起操作。您可以在两种情况下比较汇编器输出并亲自查看 - 如果您想深入了解并行性能,那么这样做非常有启发性。

答案 1 :(得分:3)

使用并发并不总是免费的。可能存在您未看到的开销,例如创建新线程,锁定内存区域等。你无法总是期望通过琐碎的任务提升性能。

您没有获得预期输出的原因是因为所有线程都使用相同的循环变量(i)。这会导致数据争用,这也是您的总和不超过500000000的原因。