Cho đến bây giờ tôi đã sử dụng std::queue
trong dự án của mình. Tôi đo thời gian trung bình mà một hoạt động cụ thể trên hàng đợi này yêu cầu.Sử dụng hàng đợi Boost.Lockfree chậm hơn so với sử dụng mutexes
Thời gian được đo trên 2 máy: Máy ảo Ubuntu cục bộ của tôi và máy chủ từ xa. Sử dụng std::queue
, mức trung bình gần như giống nhau trên cả hai máy: ~ 750 micro giây.
Sau đó, tôi "nâng cấp" std::queue
thành boost::lockfree::spsc_queue
, vì vậy tôi có thể loại bỏ các mutexes bảo vệ hàng đợi. Trên máy ảo cục bộ của tôi, tôi có thể thấy hiệu suất rất lớn, trung bình hiện tại là 200 micro giây. Tuy nhiên, trên máy từ xa, mức trung bình lên tới 800 micro giây, chậm hơn so với trước đây.
Trước tiên tôi nghĩ điều này có thể là do máy điều khiển từ xa có thể không hỗ trợ việc thực hiện lock-free:
Không phải tất cả phần cứng hỗ trợ cùng một bộ hướng dẫn nguyên tử. Nếu nó không có sẵn trong phần cứng, nó có thể được mô phỏng trong phần mềm bằng cách sử dụng bảo vệ. Tuy nhiên điều này có nhược điểm rõ ràng là mất tài sản không có khóa.
Để tìm hiểu xem các hướng dẫn này có được hỗ trợ hay không, boost::lockfree::queue
có phương pháp được gọi là bool is_lock_free(void) const;
. Tuy nhiên, boost::lockfree::spsc_queue
không có một chức năng như thế này, mà, đối với tôi, ngụ ý rằng nó không dựa vào phần cứng và đó là luôn luôn lockfree - trên bất kỳ máy nào.
Lý do mất hiệu suất là gì?
đang exmple (Nhà sản xuất/tiêu dùng)
// 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;
}
Vui lòng xem xét thêm [mcve] cho phép tạo lại các phép đo hiệu suất của bạn. Điều đó sẽ cho phép một câu trả lời thực tế hơn. – Zulan
Với sự quan tâm cao trong câu hỏi này, nó thực sự là không may rằng khía cạnh cốt lõi của sự khác biệt hiệu suất trên hai hệ thống khác nhau không thể được trả lời. Tôi nghĩ rằng có nhiều tiềm năng hơn cho một câu trả lời thực tế cụ thể nếu câu hỏi được cải thiện. – Zulan
@Zulan Tôi sẽ cố gắng thêm một ví dụ cụ thể sớm. – Bobface