Concurrency::parallel_for是否有类似omp_set_lock的命令?

Does Concurrency::parallel_for has a command similar to omp_set_lock?

我有一个 class(比如粒子),它有一个变量(比如 param1):

class particle
{
    double param1;
    . . .
    omp_lock_t particle_lck;
    . . .
};

和一个 std::vector 包含粒子的一些实例 class,

vector <particle> Particles;

在 omp parallel for 循环中,我使用以下命令在计算中安全地更新 "param1":

omp_set_lock(&currentParticle->particle_lck);
currentParticle->param1 += anything
omp_unset_lock(&currentParticle->particle_lck);

现在,我要将我的代码从 openMP 转换为并发库,我想知道是否有任何等效命令可用于 Concurrency::parallel_for 循环而不是 omp_set_lock,它可以锁定一个对象正在更新?

提前致谢。

我假设您所说的并发库是指 Microsoft 的并发运行时。您的用例实际上是一个关键部分,为此 Concurrency 提供了 concurrency::critical_section,这是一个不可重入的互斥锁:

using namespace concurrency;

class particle
{
    double param1;
    . . .
    critical_section particle_lck;
    . . .
};

那么临界区就变成了:

currentParticle->particle_lck.lock();
currentParticle->param1 += anything;
currentParticle->particle_lck.unlock();

如果您更喜欢范围内的方法,请使用 concurrency::critical_section::scoped_lock:

{
   critical_section::scoped_lock guard(currentParticle->particle_lck);
   currentParticle->param1 += anything;
}

scoped_lock 是一个简单的包装器。它需要一个 critical_section 对象的引用,并在构造函数中调用 lock(),然后在析构函数中调用 unlock(),因此它会在超出范围时释放锁。


正如 Jim Cownie 所解释的那样,将锁用于可以通过原子操作更有效地完成的事情是一种矫枉过正。在 OpenMP 中,通常会这样做:

#pragma omp atomic update
currentParticle->param1 += anything;

标准 C++ 中的原子操作需要使用特殊的原子类型,并且这些类型仅适用于从 C++20 开始的浮点类型,因此您的代码将是(假设 C++20 编译器):

#include <atomic>

class particle
{
    std::atomic<double> param1;
    . . .
};

更新值:

currentParticle->param1.fetch_add(anything, std::memory_order_relaxed);

并发不提供自己的原子类型。相反,它依赖于 combinable class 来提供与 OpenMP 的 reduction 子句等效的内容。