OpenMP -简单循环,但仍然是无限的
OpenMP - Easy Loop, but still infinite?
我在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的情况下,代码可以正常工作。但是只要我使用了编译器,代码就会卡在这个循环中。问题是:我完全不知道为什么。希望有人能帮助我
n有多大?
OpenMP parallel for
指令的默认调度是特定于实现的。看起来在GOMP (gcc使用的OpenMP实现)中,根据这里的文档,默认值是(dynamic,1)
。这意味着每个线程都在访问(在i-1
和i+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 %dn", 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++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 在C++,重复申报仍然是一个问题吗?
- "Memory Fragmentation"这仍然是一个问题?
- 将基本类型数组中的内存重新用于不同(但仍然是基本)类型的数组合法吗
- 为什么 (-i) 的类型(其中 i 是无符号的 int)仍然是无符号的 int?
- 更新 g++ 但仍然是旧版本
- 为什么这是无限递归
- boost_asio_handler_invoke_helpers::invoke 是否仍然是在 boost asio
- 是转发参考是否仍然是RVALUE参考
- 将字符串转换为整数。为什么会出现此错误?我想将 ID(字符串)更改为 IC(整数)。两者都是数组。顺便说一句,我仍然是初学者
- 派生类仍然是抽象的
- Qprocess启动的嵌套远程过程仍然是僵尸
- 为什么我的循环是无限的?我已经用 91 进行了测试
- 是shared_ptr的引用仍然是一个指针
- 为什么这条线是无限的循环
- 包裹原子类型并确保其仍然是原子
- MATLAB MEX:-STD = C 11使用,但MEX错误仍然是错误
- 循环时的输入验证是无限的
- Quantlib - 宽容仍然是一种选择
- OpenMP -简单循环,但仍然是无限的