C++(11) "High Performance" 并发单个写入器
C++(11) "High Performance" Concurrent Single Writer(s)
我有一个对象B
,由10个双值组成。双值由一个传感器产生,该传感器与并每1-2毫秒发送一次更新。B
的实例必须在程序中的其他两个位置使用做一些计算和可视化。
在另一个线程中,使用另一个传感器每隔4-10毫秒更新一个对象A
,该对象包含约1000个双值。
两个对象都有一个时间签名(当传感器的更新到达时,通过使用boost::chrono::high_resolution_clock
获取)
现在我想使用两个对象A
和B
,这两个对象在同时计算对象CCD_ 7的一些值。这应该在两个线程都在运行时完成,并且输出用于进行一些可视化、计算平均值等。整个程序运行1-2小时之后仅使用计算出的CCD_ 8s的实例,不再需要CCD_ 9和CCD_。
建议使用什么方法(或设计模式)来实现线程之间的通信和数据共享?
目前,整个结构实施得很糟糕构成CCD_ 11的线程与构成B
的线程直接通信而不使用诸如互斥锁之类的同步方法。
- 我应该使用无锁双端队列来存储
A
和B
吗并从构成CCD_ 15的线程中读取 - 我应该使用像
boost::signals2
这样的(线程安全)观察者模式来"发送"A
和B
的实例吗 - 还是其他什么
我假设您在没有实时保证的PC和操作系统上进行计算。所以,只要你在毫秒范围内,你就不会受到严格的实时限制。因此,使用无锁定数据结构并不是绝对必要的。但你可以。他们的表现也很好。如果你愿意的话,你可以使用boosts-flock-free数据结构。但是,您可能需要一个pop()
函数来阻塞,直到队列不为空,因为否则您需要进行繁忙等待,或者使用某种信号量或条件变量来等待队列不为空闲的状态。
您的争用率很低,而且只有几个线程。在低争用下锁定互斥体通常需要大约25ns。所以这不是问题。如今,内存分配通常也非常快,通常平均不到100ns。我的看法是:
-
使用
std::queue<std::packaged_task<void()>>
作为任务队列。如果计算结果不需要std::future
s,您也可以决定将std::function<void()>
而不是std::packaged_task<void()>()
排入队列。使用std::mutex
保护对它的访问。有一个std::condition_variable
在那里等待队列非空。我曾经在github上实现了一个通用的阻塞并发队列,它比这更高效,但只使用标准的库方法。您只需要将模板参数指定为T=std::packaged_task<void()>
,就可以获得所需的数据结构。 -
创建一个只执行传入任务的线程
std::thread
。要退出线程,请在线程的最后一个任务中设置一些std::atomic<bool>
标志,这样线程就会停止执行,您可以优雅地join()
它。同样,您可以将该功能放入一个类中。类的析构函数应该告诉任务执行线程停止并执行join()
。我在github上的同一个存储库中实现了这样一个类。你可以自由使用。 -
现在,您可以从接收硬件数据的两个线程将任务传递给任务执行器。只需将适当的lambda传递给执行需要完成的工作的任务执行器。如果你决定使用我的实现,你可以写一些类似的东西
void receiveData( const Data & data, cu::ParallelExecutor & executor ) { executor.addTask( [=]{ /* Do something with `data` */ } ); }
这样,一切都是线程安全的,具有低开销和高性能。
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 控制允许动态运行c++的并发操作数
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 用C++快速读写文件
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- USB-HID 读/写(重叠)等待单个对象不返回C++
- 如何使用单个解锁方法(可称为读取器或写入器)实现C++读写器锁?
- 具有并发读写功能的嵌入式数据库
- C++(11) "High Performance" 并发单个写入器
- 读/写void*变量的单个字节
- 并发修改和读取单个全局变量
- Linux中的STL容器和线程(并发写)
- 可能并发写*相同*值到整数.我需要一个原子变量吗?
- 使用单个写操作写入多个VA位置
- 单个进程中有数千个读/写锁
- 具有独立读线程和写线程的单个队列是否需要锁定
- 如何避免并发写导致的非确定性读