gpt4 book ai didi

c++ - OpenMP - Easy Loop,但仍然是无限的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:45:40 26 4
gpt4 key购买 nike

我在 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 个元素的 double 组。在没有 OpenMP 的情况下使用代码时,代码工作正常。但是一旦我使用 pragma,代码似乎就陷入了这个循环。问题是:我完全不知道为什么。希望有人能帮助我

最佳答案

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)

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

最后,您可能还想将 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

关于c++ - OpenMP - Easy Loop,但仍然是无限的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8041193/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com