boost::unique_lock,多次读取会减慢写入速度
boost::unique_lock, multiple reads are slowing down the writer
我有一个应用程序,我使用boost::shared_mutex
锁定在一个线程中写入cv::Mat
,然后从许多其他线程调用它。
这本书写得很好,但阅读量太多会让作者慢下来。我想,这是因为写作是在等待所有的阅读完成。有没有一种不同的boost
锁可以让编写器全速运行,有很多读者?还是我需要找到另一种方法来解决这个问题?
我的相关代码是:
//writer.h
cv::Mat currentFrame;
typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
Lock frameLock;
//writer.cpp
WriteLock w_lock(frameLock);
cv_img.copyTo(currentFrame);
frameLock.unlock();
//阅读器.h
typedef boost::shared_mutex Lock;
typedef boost::shared_lock< Lock > ReadLock;
//reader.cpp
cv::Mat frame;
ReadLock r_lockz(writer->frameLock);
writer->currentFrame.copyTo(frame);
_lockz.unlock();
谢谢。
此处互斥的全部目的是防止读/写冲突。当一个较慢的进程锁定资源时,速度会减慢。
您当前的方法始终存在瓶颈;你需要找到另一个。也许是不同类型的并发(多个读写器?)。
您可以尝试双重缓冲,即使用两个cv:Mat
(帧)实例并在它们之间交替。
在从"活动"帧读取(可以是并行的)的同时(按顺序)写入"非活动"帧。写入新帧后,将其指定为"活动",将另一帧指定为"非活动"。
共享状态:
cv::Mat currentFrame[2];
std::shared_mutex frameMutex[2];
std::mutex writeMutex;
std::atomic<int> activeFrame = 0;
编写器实现:
std::unique_lock<std::mutex> writeLock(writeMutex);
const int writeFrame = activeFrame ^ 1;
std::unique_lock<std::shared_mutex> frameLock(frameMutex[writeFrame]);
cv_img.copyTo(currentFrame[writeFrame]);
activeFrame = writeFrame;
阅读器实现:
const int readFrame = activeFrame;
std::shared_lock<std::shared_mutex> frameLock(frameMutex[readFrame]); // lock shared
currentFrame[readFrame].copyTo(frame);
人们的假设是阅读比写作快得多。否则,仍将存在一些锁争用。
对代码进行一点重构,并将"Writer"类中的currentFrame(和相关锁)提取到一个单独的共享"State"类中,这可能是一个好主意。
与其复制,不如分配它并创建一个新的cv::Mat,本质上是一个shared_ptr
//writer.h
cv::Mat currentFrame;
typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
Lock frameLock;
//writer.cpp
WriteLock w_lock(frameLock);
currentFrame = cv_img;
frameLock.unlock();
//reader.h
typedef boost::shared_mutex Lock;
typedef boost::shared_lock< Lock > ReadLock;
//reader.cpp
cv::Mat frame;
ReadLock r_lockz(writer->frameLock);
frame = writer->currentFrame;
_lockz.unlock();
cv_img只是当前使用的缓冲区的前端。读卡器将获得一个在读取周期中期不会改变的缓冲区(但可能在完成之前与当前帧不同步),但其帧的范围决定了每个缓冲区的寿命。
通过进行深度复制,您在shared_ptr(cv::Mat)中创建了一个缓冲区,然后对它的每个用户进行完整复制,而不是创建一个不可变的缓冲区,当每个人都完成时,这个缓冲区就会超出范围。锁定将保持修改。顺便说一句,你可能想考虑在关键部分使用scoped_lock,并在其周围放置大括号或scope。这样,如果你扔了或忘记解锁它,就不会破坏一切。
{
boost::scoped_lock(frameLock);
currentFrame = cv_img;
}
如果您有很多争用,并且是锁定时间(没有争用的锁并不是"那么糟糕"),那么无锁队列可能会工作
#include <boost/lockfree/spsc_queue.hpp>
// writer.h
using cv_queue_t = boost::lockfree::spsc_queue<cv::Mat>// cv::Mat might need this to be wrapped for contructor requirements
cv_queue_t cv_queue;
// writer.cpp
while( !cv_queue.push( cv_img ) ) { // could put a sleep in here }
// reader.cpp
while( !writer->cv_queue.pop( frame ) ) { // could put sleep in here }
- 为什么在读取文件大小时文件IO速度会发生变化
- 加快在C++中读取/处理日志文件的速度
- 如何提高文件的读取速度?
- QT 5.7 串口读取速度很慢
- 如何在 Ubuntu 上提高我的程序磁盘读取速度
- boost::unique_lock,多次读取会减慢写入速度
- C++-为什么标记化器从文件中读取行的速度如此之慢
- 对齐数据:速度取决于恒定数据读取的相对采样大小和采样频率
- C++ 提供 SSE 指令,以最快的速度读取文件
- C++ ifstream::由于memcpy,读取速度慢
- 为什么从内存映射文件中读取速度如此之快
- 可以提高iostream读取和压缩gzip文件的速度
- Windows XP在C++中启动时读取文本文件的速度较慢;预取
- FILE_FLAG_IO_BUFFERING会减慢同步读取操作的速度
- STL文件的哪种格式读取速度更快:ascii还是二进制
- C++逐行读取文本,需要节省速度/效率
- QTcpSocket每~0.5s才读取一次数据,即使是非常小的数据包,任何方法都可以加快速度
- 速度控制在100Hz至10KHz范围内读取小记录从文件上的窗口
- 如何加快从流到内存的读取速度
- 如何使用c++在Windows上提高读取数据的速度