I have a class (say particle) which has a variable (say param1):
class particle
{
double param1;
. . .
omp_lock_t particle_lck;
. . .
};
and a std::vector containing some instances of the particle class,
vector <particle> Particles;
In omp parallel for loop, I use commands below to safely update "param1" in computations:
omp_set_lock(¤tParticle->particle_lck);
currentParticle->param1 += anything
omp_unset_lock(¤tParticle->particle_lck);
Now, I am going to convert my code from openMP to Concurrency library, I am wondering if there are any equivalent command to use in Concurrency::parallel_for loop instead of omp_set_lock, which can lock an object while is updating?
Thanks in advance.
I assume that by Concurrency library you mean Microsoft's Concurrency Runtime. Your use case is actually a critical section and for that Concurrency provides the concurrency::critical_section
, which is a non-reentrant mutex lock:
using namespace concurrency;
class particle
{
double param1;
. . .
critical_section particle_lck;
. . .
};
Then the critical section becomes:
currentParticle->particle_lck.lock();
currentParticle->param1 += anything;
currentParticle->particle_lck.unlock();
If you prefer a scoped approach, use concurrency::critical_section::scoped_lock
:
{
critical_section::scoped_lock guard(currentParticle->particle_lck);
currentParticle->param1 += anything;
}
scoped_lock
is a simple wrapper. It takes a reference to a critical_section
object and calls lock()
in the constructor and then unlock()
in the destructor, so it releases the lock when it goes out of scope.
As explained by Jim Cownie, using locks for something that can be done more efficiently with an atomic operation, is an overkill. In OpenMP, one would usually do:
#pragma omp atomic update
currentParticle->param1 += anything;
Atomic operations in standard C++ require the use of special atomic types and those are only trully available for floating-point types starting with C++20, so your code will be (assuming C++20 compiler):
#include <atomic>
class particle
{
std::atomic<double> param1;
. . .
};
Updating the value:
currentParticle->param1.fetch_add(anything, std::memory_order_relaxed);
Concurrency does not provide its own atomic types. Instead, it relies on the combinable
class to provide an equvalent to OpenMP's reduction
clause.