OpenMP - Easy Loop,但仍然无限?

时间:2011-11-07 18:59:46

标签: c++ parallel-processing openmp

在我的C ++代码中使用OpenMP时遇到了一个非常奇怪的问题:

void update(double *source, double *target, int n)
{
    target[0] = source[0];
    target[n-1] = source[n-1];
    #pragma omp parallel for 
    for(int i = 1; i < n-1; ++i) 
        target[i] = (1.0/3.0) * (source[i-1] + source[i] + source[i+1]);
}

源和目标都是具有n个元素的双数组。在没有OpenMP的情况下使用它时,代码工作正常。但是一旦我使用pragma,代码就会陷入这个循环中。问题是:我绝对没有IDEA为什么。希望有人能帮助我

1 个答案:

答案 0 :(得分:2)

n有多大?

OpenMP parallel for指令的默认调度是特定于实现的。它看起来像在GOMP(gcc使用的OpenMP实现)中,根据documentation here,默认值为(dynamic,1)。这意味着每个线程正在访问(在i-1i+1)相邻线程加载的内存位置,这可能导致缓存利用率较低。在现代CPU架构中,像这样的模板操作通常受内存限制并且对缓存敏感。您可以尝试使用更大的块来指定计划,例如:

#pragma omp parallel for schedule(dynamic,1024)

我这里仅以1024为例。实际上,您应该尝试找到最佳的分块因子(或者使用参数扫描系统地搜索,这个过程通常称为“自动调整”)。或者您可以在理论上选择更多的值,例如从CPU的L1或L2缓存大小中推导出来。

或者您可以尝试静态调度,因为for循环内部的计算量在线程间是统一的,并且动态调度程序的开销可能会导致瓶颈。如果您指定

#pragma omp parallel for schedule(static)

没有块大小,那么每个线程将被分配一个大小相同的块。

最后,您可能还希望将OpenMP线程固定到自己的CPU核心。您可以使用GOMP_CPU_AFFINITY环境变量执行此操作。

编辑:

我刚刚使用gcc 4.2.1编译的以下测试程序,我认为我上面链接的文档不正确。看起来GOMP默认为schedule(static)

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

int main(int argc, char** argv)
{
    int i;
    #pragma omp parallel for
    for (i=0; i<15; i++) {
        int id = omp_get_thread_num();
        printf("%d assigned to thread %d\n", i, id);
    }
}

两个线程的输出是:

$ ./test_sched | sort -n
0 assigned to thread 0
1 assigned to thread 0
2 assigned to thread 0
3 assigned to thread 0
4 assigned to thread 0
5 assigned to thread 0
6 assigned to thread 0
7 assigned to thread 0
8 assigned to thread 1
9 assigned to thread 1
10 assigned to thread 1
11 assigned to thread 1
12 assigned to thread 1
13 assigned to thread 1
14 assigned to thread 1