std::queue
。我测量了针对此队列的特定操作所需的平均时间。这些时间是在2台机器上测量的:我的本地Ubuntu虚拟机和远程服务器。 使用
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
没有像这样的函数,这意味着它不依赖于硬件,并且总是无锁的-在任何机器上。那么性能下降的原因是什么?
示例代码(生产者/消费者)
// 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;
}
rand
。应该使用 C++11 的<random>
或者rand_r
,参见。你如何计时代码并且它如何对应你的性能观察? - Zulanis_lock_free
就意味着什么是不正确的。在实现中,我们可以看到它们都使用原子操作,这些操作直接依赖于CPU支持。 - yano