使用boost.lockfree队列比使用静音速度慢
Using Boost.Lockfree queue is slower than using mutexes
到目前为止,我在项目中使用了std::queue
。我测量了该队列所需的特定操作所需的平均时间。
在两台机器上测量了时间:我的本地Ubuntu VM和一台远程服务器。使用std::queue
,两台机器上的平均值几乎相同:〜750微秒。
然后我将std::queue
"升级"到boost::lockfree::spsc_queue
,因此我可以摆脱保护队列的静音。在当地的VM上,我可以看到巨大的性能增长,平均值现在是200微秒。但是,在远程机器上,平均水平高达800微秒,这比以前慢。
首先,我认为这可能是因为远程计算机可能不支持无锁的实现:
摘自boost.lockfree页面:
并非所有硬件都支持相同的原子说明。如果硬件不可用,则可以在使用警卫的软件中模拟它。但是,这显然是失去无锁属性的缺点。
要找出是否支持这些说明,boost::lockfree::queue
具有称为bool is_lock_free(void) const;
的方法。但是,boost::lockfree::spsc_queue
没有这样的函数,对我而言,这意味着它不依赖硬件,并且在任何计算机上始终是无锁的。
表现损失的原因是什么?
Exmple代码(生产者/消费者(
// c++11 compiler and boost library required
#include <iostream>
#include <cstdlib>
#include <chrono>
#include <async>
#include <thread>
/* Using blocking queue:
* #include <mutex>
* #include <queue>
*/
#include <boost/lockfree/spsc_queue.hpp>
boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024>> queue;
/* Using blocking queue:
* std::queue<int> queue;
* std::mutex mutex;
*/
int main()
{
auto producer = std::async(std::launch::async, [queue /*,mutex*/]()
{
// Producing data in a random interval
while(true)
{
/* Using the blocking queue, the mutex must be locked here.
* mutex.lock();
*/
// Push random int (0-9999)
queue.push(std::rand() % 10000);
/* Using the blocking queue, the mutex must be unlocked here.
* mutex.unlock();
*/
// Sleep for random duration (0-999 microseconds)
std::this_thread::sleep_for(std::chrono::microseconds(rand() % 1000));
}
}
auto consumer = std::async(std::launch::async, [queue /*,mutex*/]()
{
// Example operation on the queue.
// Checks if 1234 was generated by the producer, returns if found.
while(true)
{
/* Using the blocking queue, the mutex must be locked here.
* mutex.lock();
*/
int value;
while(queue.pop(value)
{
if(value == 1234)
return;
}
/* Using the blocking queue, the mutex must be unlocked here.
* mutex.unlock();
*/
// Sleep for 100 microseconds
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
}
consumer.get();
std::cout << "1234 was generated!" << std::endl;
return 0;
}
锁定算法通常比基于锁定的算法更差。这是它们不经常使用的关键原因。
锁定算法的问题是,它们通过允许竞争线程继续争夺来最大程度地提高争议。锁避免通过拆卸线程的螺纹来避免争夺。仅在无法去除线程的线程时,才应使用锁定免费算法,直到第一个近似值。这很少适用于应用程序级代码。
让我给你一个非常极端的假设。想象一下四个线程正在典型的现代双核CPU上运行。线程A1和A2正在操纵集合A。线程B1和B2正在操纵集合b。
首先,让我们想象该系列使用锁。这将意味着,如果线程A1和A2(或B1和B2(尝试同时运行,则其中一个将被锁定。因此,很快,将运行一个线程和一个B线程。这些线程将非常快速运行,并且不会争夺。任何时间线程都尝试争夺,冲突的线程将被删除。是的。
现在,想象该系列没有锁。现在,线程A1和A2可以同时运行。这将导致不断的争论。该集合的缓存线将在两个内核之间ping-pong。核心总线可能会饱和。性能会很糟糕。
再次,这是高度夸张的。但是你明白了。您想避免争论,不要遭受尽可能多的苦难。
但是,现在再次运行此思想实验,其中A1和A2是整个系统中唯一的线程。现在,免费锁定收集可能会更好(尽管您可能会发现在这种情况下只有一个线程更好!(
。几乎每个程序员都经历了一个阶段,他们认为锁不好并且避免锁会使代码变得更快。最终,他们意识到这是的争论使事情变得缓慢而锁定,正确使用,最小化争夺。
我不能说在所有可能的情况下,Boost Rockfree队列都较慢。根据我的经验,推动(const t&amp; item(正在尝试制作副本。如果您要构造TMP对象并推到队列,则会被性能阻力击中。我认为库只需要超载版本推动(t&amp; emp; item(即可使可移动对象更有效。在添加新功能之前,您可能必须使用指针,普通类型或C 11之后提供的智能功能。这是队列的一个相当有限的方面,我只使用无锁队列差异很少。
- CUDA Shuffle指导减少速度慢于减少共享记忆
- 使用boost.lockfree队列比使用静音速度慢
- 提升文件系统的速度慢得令人难以置信
- Winsock C++ - Java 连接速度慢
- Qt自定义树模型显示正确,但有缺陷且速度慢
- C++线程化的应用程序比非线程化的运行速度慢
- 函数调用速度慢得令人痛苦
- gcc std::unordered_map 实施速度慢吗?如果是这样 - 为什么
- 返回元素的速度比通过引用和修改发送元素的速度慢
- A* 寻路速度慢
- 流网络摄像头的速度慢,无法"detectMultiScale"
- 相同的功能?使用 GMP(C++) 时运行速度慢约 10 倍
- C++ 多线程处理速度慢
- C++ ifstream::由于memcpy,读取速度慢
- 运行时间比较 - 类似的代码运行速度慢 4 倍
- 大桌子的快速排序速度慢得出奇
- 在c++中重写这个python函数似乎会使其运行速度慢很多.这合理吗
- 在空中曲棍球比赛中,我怎样才能使冰球的速度慢下来?
- 编译后首次执行速度慢得令人难以置信,除非"obvious"所有循环都将停止
- 与CPU版本相比,OpenCV GPU对象检测速度慢,检测次数少