我是新来的OpenMp世界,并得到了一个错误,我无法修复。原来的代码是大的,所以我做了一个小代码来总结这个问题:
我得到了一个更多维的std::vector (2d和3d),它不应该在线程之间共享。如果我将它们标记为私有,它们仍然会导致内存错误,因为线程仍然共享它们。
我想出了一个解决这个问题的方法:我为2d向量多创建了一个维度,这样每个线程都可以访问自己的副本:
myVector[omp_get_thread_num()][1].push_back(i);我知道这对我的问题不是一个聪明的解决办法,但是现在每个线程都有自己的2d向量副本。现在出现了一个奇怪的部分:如果我不把#pragma omp critial放在前面的话,这仍然会导致内存崩溃。我真的不明白为什么它是必要的,因为线程不应该访问相同的内存。
#include <iostream>
#include <omp.h>
#include <vector>
//this should represent my problem(without my fix)
int main(){
std::vector < std::vector < int > > v;
v.resize(3);
#pragma omp parallel for num_threads(2) private(v)
for(int i = 0; i < 10; i++){
v[1].push_back(i);
}
return 0;
}我希望有一个更好的解决方案,使我的2d向量线程私有。
ps。无法在omp部件内分配向量。
发布于 2019-07-03 10:39:45
您必须理解来自被声明为private的外部作用域的变量的工作方式,就好像它们是在本地声明的,而没有初始化器。因此,每个本地副本都是一个空向量,因此您的代码无法工作。
通常,使用OpenMP在本地声明私有变量更好--这样可以避免“外部值”和“内部私有值”之间的许多混淆,它们根本没有关联。您可以通过拆分parallel和for指令来做到这一点。
#pragma omp parallel
{
std::vector<std::vector<int>> v;
v.resize(3);
#pragma omp for
for(int i = 0; i < 10; i++){
v[1].push_back(i);
}
}注意,v在并行区域之后是不可用的--这很好!在您最初的示例中,v在并行区域之后可用-但是它的值与来自内部线程的值无关。
如果您需要保留来自v的信息,您可能需要查看简化,但这取决于您的特定用例。
您的myVector[omp_get_thread_num()]方法是一种常见的天真方法。这段代码是正确的,但是在任何情况下,当您修改最外层向量的值时,由于错误共享,它具有性能差的。
myVector[omp_get_thread_num()].push_back(); // Bad performance
myVector[omp_get_thread_num()][1].push_back(i); // Ok因此,通常建议不要这样做,而是使用本地声明的变量。尽管如此,如果您的代码崩溃,还有其他问题。在这种情况下,您需要准备一个minimal reproducible example,并提出第二个问题(引用此)。
现在,threadprivate与private有所不同。private通常是您想要的,它指的是特定的任务/范围。在大多数情况下,您不需要或不需要threadprivate。
https://stackoverflow.com/questions/56867480
复制相似问题