有效的记忆障碍

时间:2011-09-08 09:52:08

标签: c++ linux

我有一个多线程应用程序,其中每个线程都有一个整数类型的变量。这些变量在程序执行期间递增。在代码中的某些点,线程将其计数变量与其他线程的计数变量进行比较。

现在,我们知道在多核上运行的线程可能无序执行,线程可能无法读取其他线程的预期计数器值。要解决这个问题,一种方法是使用原子变量,例如std :: atomic<> C ++ 11但是,在每个计数器增量处执行内存栅栏将大大减慢程序的速度。

现在我想要做的是,当一个线程即将读取其他线程的计数器时,只有这样才会创建一个内存栅栏,并在该点内存更新所有线程的计数器。如何在C ++中完成。我正在使用Linux和g ++。

6 个答案:

答案 0 :(得分:4)

C ++ 11标准库包含对<atomic> std::atomic_thread_fence中围栏的支持。

调用此方法会调用完整的栅栏:

std::atomic_thread_fence(std::memory_order_seq_cst);

如果您只想发布获取或仅发布版本围栏,则可以使用std:memory_order_acquirestd::memory_order_release代替。

答案 1 :(得分:1)

x86内在函数对应于您可以自己使用的内存屏障。 Windows标头有一个内存屏障宏,因此您应该能够找到与Linux等效的内容。

答案 2 :(得分:0)

我的建议是在更高级别的类中有一个collectTimers()函数,可以向每个线程询问其计数器(通过queue / msg)。这样更新计时器不会延迟,但收集计时器会慢一些。

只有在线程之间有某种通信机制时,这才有效。

答案 3 :(得分:0)

为什么不拥有一个“控制”线程,每个线程向谁报告其计数器增量并询问其他人的值?

这将使它非常有效和简单。只是一个建议。

答案 4 :(得分:0)

您可以尝试使用http://mirror.nexcess.net/kernel.org/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf

的Secion 4.4.3中的信号窃取限制计数器设计

这种设计可以消除快速路径中的原子操作(递增每线程计数器)。当然,复杂性是否值得由你来决定。

答案 5 :(得分:-1)

您可以将boost :: asio :: strand用于此目的。创建一个负责读取计数器的处理程序。可以从多个线程调用该处理程序。而不是直接调用处理程序,将其包装在boost :: asio :: strand中。这将确保多个线程不能同时调用处理程序。

http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/tutorial/tuttimer5.html

我希望我能正确理解这个问题。