访问类数据时互斥锁/解锁的替代方案
我试图像这样使 my_class
线程安全。
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()
和 get_data()
可能由不同的 openmp
线程调用,因此我引入了一个锁。 (由于我使用 openmp,m_mutex
和 lock
是 omp_init_lock();
等命令的 RAII 包装器)。
但是,创建和销毁 get_data ()
上的锁的成本很高(当我分析代码时最昂贵的操作 - 我经常调用 get_data()
)。
是否可以重新组织 my_class 以删除 get_data()
中的锁?或者这个锁是并行代码不可避免的成本吗?
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 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
第一步是研究读写锁:这样多个读取器就不会互相阻塞。
下一步将是使用无锁或无等待操作。网上有很多资源比我能更好地描述它们。请注意:无锁方法处理原子(互锁)操作,这意味着数据大小需要很小。如果您走这条路,您将自动替换指向向量的指针,而不是整个向量。这意味着您的类将变得更加复杂,并且将处理一些指针和内存管理。
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.
在 get_data/run 函数周围使用关键部分可能会更便宜,您不会产生额外的设置/拆卸开销(因为关键部分是静态初始化的),但这也会同步该类的其他实例。
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.