I am trying to make my_class
thread-safe like so.
class my_class
{
const std::vector<double>&
get_data() const
{ //lock so that cannot get_data() while setting data
lock l(m_mutex);
return m_data;
}
void
run()
{
vector<double> tmp;
//some calculations on tmp.
{ //lock so that cannot get_data() while setting m_data
lock l(m_mutex);
m_data = tmp; //set the data
}
}
private:
std::vector<double> m_data;
mutex m_mutex;
my_class(); //non-copyable
}
run()
and get_data()
may be called by different openmp
threads and so I introduce a lock.
(Since开发者_Python百科 am using openmp, m_mutex
and lock
are RAII wrappers around omp_init_lock();
etc. commands).
However, the lock on get_data ()
is expensive to create and destroy (The most expensive operation when I profile my code - I call get_data()
a lot).
Is is possible to reorganise my_class to remove the lock in get_data()
? Or is this lock the unavoidable cost of parallelising the code?
First step would be to look into read-write locks: this way multiple readers will not block each other.
The next step would be using lock-free or wait-free operations. There are plenty of resources online describing them better than I would be able to. Just one note: lock-free approaches deal with atomic (interlocked) operations, which means the data size needs to be small. If you go this route, you'll be atomically replacing a pointer to your vector, not the whole vector. This means your class will get a bit more complex and will deal with some pointers and memory management.
It may be cheaper to use a critical section around get_data/run functions, you will not incur additional setup/teardown overhead (as the critical section is statically initialized), but this would also synchronize other instances of the class.
精彩评论