gpt4 book ai didi

c++ - OpenMp:如何使维度 std::vector threadprivate

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:02:37 25 4
gpt4 key购买 nike

我是 OpenMp 世界的新手,遇到了一个错误,我无法修复。原始代码太大了,所以我做了一个小代码来总结问题:

我得到了一个更多维的 std::vector(2d 和 3d),它不应该在线程之间共享。如果我将它们标记为私有(private),它们仍然会导致内存错误,因为线程仍然共享它们。

我想出了一个解决这个问题的办法:我为 2d vector 创建了 1 个维度,因此每个线程都可以访问他自己的拷贝:

myVector[omp_get_thread_num()][1].push_back(i);

我知道这不是我的问题的明智解决方案,但现在每个线程都有自己的 2d Vector 拷贝。现在奇怪的部分来了:如果我不把 #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 vector 线程私有(private)。

附言。不可能在 omp 部分内部分配 vector 。

最佳答案

您必须了解来自外部作用域的声明为 private 的变量的工作方式就好像它们是在没有初始化程序 的本地声明的一样。因此每个本地拷贝都是一个空 vector ,因此您的代码无法运行。

通常,OpenMP 最好在本地声明私有(private)变量 - 这样可以避免根本不相关的“外部值”和“内部私有(private)值”之间的大量混淆。您可以通过拆分 parallelfor 指令来做到这一点。

#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()] 的方法是一种常见的幼稚方法。此代码正确,但在您修改最外层 vector 的值的任何情况下,由于错误共享,它都会性能不佳

myVector[omp_get_thread_num()].push_back(); // Bad performance
myVector[omp_get_thread_num()][1].push_back(i); // Ok

因此通常不建议这样做,而是使用局部声明的变量。然而,如果你的这段代码崩溃了,那就是其他地方出了问题。在这种情况下,您需要准备一个 minimal reproducible example并请问第二个问题(引用这个)。

现在 threadprivate 不同于 privateprivate 通常是您想要的,指的是特定任务/范围。在大多数情况下,您不需要或不需要 threadprivate

关于c++ - OpenMp:如何使维度 std::vector threadprivate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56867480/

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