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(¤tParticle->particle_lck);
currentParticle->param1 += anything
omp_unset_lock(¤tParticle->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
子句等效的内容。
我有一个 class(比如粒子),它有一个变量(比如 param1):
class particle
{
double param1;
. . .
omp_lock_t particle_lck;
. . .
};
和一个 std::vector 包含粒子的一些实例 class,
vector <particle> Particles;
在 omp parallel for 循环中,我使用以下命令在计算中安全地更新 "param1":
omp_set_lock(¤tParticle->particle_lck);
currentParticle->param1 += anything
omp_unset_lock(¤tParticle->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
子句等效的内容。