【问题标题】:OpenMP STL set container iteratorOpenMP STL 设置容器迭代器
【发布时间】:2015-04-07 04:11:04
【问题描述】:
我有一个与这里提出的问题类似的问题 -OpenMP parallel thread。我希望并行化 for 循环涉及 std::set 迭代器。所以我正在尝试研究@Hristo lliev 提供的答案。我不太确定。
如果一个线程没有选择一个任务,那么它的“worst_q”应该是它进入临界区时的原始数字。但是如果一个线程拿起一个任务,并且“t_worst_q”将在任务内部发生变化,那么当这个线程进入临界区时,这个“t_worst_q”将保持与它在任务构造中的相同,我正确吗?但是,我用了一个例子,它看起来不像这样,也许我仍然遗漏了一些东西。
【问题讨论】:
标签:
c++
multithreading
stl
openmp
【解决方案1】:
是的,您解释它的方式是“Hristo Iliev”希望它如何工作。不幸的是,他在任务方面搞错了几件事:
他使用taskwait 的所谓“屏障”仅适用于创建任务的线程。所有其他线程都通过它运行。所以他最终的整个减少是无用的,因为大多数线程在他们实际做任何工作之前执行它。 “taskwait”旨在帮助解决数据依赖关系(非常有用in recursive functions!),这就是它以这种方式工作的原因。
程序有时工作的唯一原因,即使最后没有减少功能,是他的第一个错误被第二个错误部分抵消:任务中的变量t_worst_q引用了线程中的那个生成任务,因此充当全局变量。但是,当然,我们在std::min 中有一个竞争条件,这仍然让代码有时会失败。
所以实际上他的代码等价于以下代码:
#pragma omp parallel
{
// Create tasks
#pragma omp single nowait
{
for(std::set<size_t>::const_iterator it=mesh->NEList[vid].begin();
it!=mesh->NEList[vid].end(); ++it) {
size_t elem = *it;
#pragma omp task shared(worst_q)
worst_q = std::min(worst_q, mesh->element_quality(elem));
}
}
}
如前所述,这在执行std::min 时存在访问worst_q 的竞争条件的问题。如果函数mesh->element_quality 与std::min 函数相比计算量大,那么一个简单的解决方案是在std::min 部分周围设置一个临界区(在临界区外执行mesh->element_quality 之后)。另一方面,如果mesh->element_quality 不比std::min 贵,那么临界区将扼杀并行性。但在这种情况下,mesh->element_quality 函数非常便宜,以至于管理任务的开销无论如何都会消耗掉所有潜在的加速。