【问题标题】:C++17 for_each parallelC++17 for_each 并行
【发布时间】:2021-08-21 09:38:08
【问题描述】:

我想问一下如何并行化以下循环。 它目前正在崩溃。我尝试搜索,大多数答案表明问题在于我使用的是std::vector。我试图制作一个固定大小的std::vector。但是应用程序仍然崩溃。你能告诉我下面的循环有什么问题吗?

    std::vector<int> a(pairsListFlags.size());
    std::generate(a.begin(), a.end(), [n = 0]() mutable { return n++; });
    

    std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int i) {

        int a = pairsList[i * 2];
        int b = pairsList[i * 2 + 1];
        if (getCollisionOpenNurbs(OBB[a], OBB[b])) {   //Check OBB collision +4-6 ms  
            if (FaceFace(P[a], P[b], Pl[a], Pl[b])) {//Check polygon intersection +20 ms
                pairsListFlags[i] = 1;
                
            }
        }

    });

【问题讨论】:

  • 您正在同时访问一个非原子变量 (counter),这是未定义的行为。除此之外,我们需要知道在 lambda 中调用的所有函数中发生了什么。
  • getCollisionOpenNurbs 方法检查 2 个盒子是否碰撞。 FaceFace 方法使用剪裁器库进行二维折线相交。我应该如何知道这些函数对于并行循环是否不安全?我应该避免什么?

标签: c++ loops parallel-processing c++17


【解决方案1】:

你的问题不是令人尴尬的并行,所以你不应该在这里使用std::for_each(至少在没有同步机制或低效的原子时不能使用)。相反,您可以使用std::reduce 执行缩减。这是一个例子:

std::vector<int> a(pairsListFlags.size());
std::generate(a.begin(), a.end(), [n = 0]() mutable { return n++; });
int counter = std::reduce(std::execution::par_unseq, std::begin(a), std::end(a), 0, [&](int i) {
    int a = pairsList[i * 2];
    int b = pairsList[i * 2 + 1];
    if (getCollisionOpenNurbs(OBB[a], OBB[b])) {   //Check OBB collision +4-6 ms  
        if (FaceFace(P[a], P[b], Pl[a], Pl[b])) {  //Check polygon intersection +20 ms
            pairsListFlags[i] = 1;
            return 1;
        }
    }
    return 0;
});

请注意,您应该小心pairsListFlags 上的虚假共享,因为它可能会稍微降低生成代码的性能(但对结果没有影响)。

【讨论】:

  • 我想我可以完全跳过计数器。这个 reduce 循环会在第一个 boolean true 之后终止吗?我从原始帖子中删除了,因为它令人困惑。
  • 好的,这改变了问题。没有counter,减少就不再有用了。请注意,getCollisionOpenNurbsFaceFace 需要是线程安全的(如果可能的话是无锁的,或者更好的是:无等待)。减少不会提前停止,所有整数值都将被计算和求和。请注意,返回值是 int 而不是 bool。如果您想提前停止循环并测试是否有任何检查为真,那么您可以使用std::any_of。除此之外,pairsList.size() 必须至少为 a.size()*2PPl 也必须具有正确的大小。我建议你使用 assertions.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2021-11-29
  • 1970-01-01
  • 2019-04-06
  • 2011-01-05
  • 1970-01-01
相关资源
最近更新 更多