OpenMP条件严重
问题描述:
首先,请记住,我不是OpenMP的非常频繁的用户......好吗?OpenMP条件严重
现在我们已经过去了,是否有条件的critical
?
我在这条线并行for
循环内特别感兴趣:
(...)
#pragma omp critical
myMapOfVectors[i].push_back(someNumber);
(...)
我想有它critical
当且仅当运行这个特定的行具有相同的i
(因为我有螺纹一直在经历着 - 如果我错了,请在这里纠正我 - 多个线程推回到相同的vector
不是线程安全的并可能导致segfault
)。
答
你需要的是每个索引i
有一个lock。
// before you parallel region
std::vector<omp_lock_t> myLocks(myMapOfVectors.size());
for (size_t i = 0; i < myLocks.size(); ++i) {
omp_init_lock(myLocks+i);
}
...
omp_set_lock(myLocks[i]);
myMapOfVectors[i].push_back(someNumber);
omp_unset_lock(myLocks[i]);
...
// after your parallel region
for (size_t i = 0; i < myLocks.size(); ++i) {
omp_destroy_lock(myLocks+i);
}
临界区是本质上只是一个单一的锁,通过具有针对每个索引的单独临界段多个锁你在本质上的仿。
请记住,锁定速度可能会很慢(特别是如果有碰撞)。如果您可以提前对工作进行分区(即,每个线程在不同的索引集i
上工作,或者每个线程都拥有自己的副本myMapOfVectors
,以后再合并),您可能会获得更好的性能。
谢谢您的回答!我喜欢你的解决方案,但我希望有一些指令可以帮助我完成繁重的工作。我的意思是,这就是为什么我们有OpenMP,不是吗? :P不是对您的投诉,只是对OpenMP的批评... –
因为编译指示是编译时指示,所以它们不能用于在动态分配的堆对象上进行同步(至少在一般情况下)。如果你实现了自己的栈对象(具有固定的内存分配),你可以使用'#pragma omp atomic'在内部插入元素(插入不会是原子性的,但增加计数)。 – dlasalle