【发布时间】:2015-06-12 23:58:40
【问题描述】:
我正在使用 boost spsc_queue 将我的东西从一个线程移动到另一个线程。这是我软件中的关键位置之一,所以我想尽快完成。我写了这个测试程序:
#include <boost/lockfree/spsc_queue.hpp>
#include <stdint.h>
#include <condition_variable>
#include <thread>
const int N_TESTS = 1000;
int results[N_TESTS];
boost::lockfree::spsc_queue<int64_t, boost::lockfree::capacity<1024>> testQueue;
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
int totalQueueNano(0);
int totalQueueCount(0);
void Consumer() {
int i = 0;
int64_t scheduledAt;
while (i < N_TESTS - 1) {
while (testQueue.pop(scheduledAt)) {
int64_t dequeuedAt = (duration_cast<nanoseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())).count();
auto diff = dequeuedAt - scheduledAt;
totalQueueNano += diff;
++totalQueueCount;
results[i] = diff;
++i;
}
}
for (int i = 0; i < N_TESTS; i++) {
printf("%d ", results[i]);
}
printf("\nspsc_queue latency average nano = %d\n", totalQueueNano / totalQueueCount);
}
int main() {
std::thread t(Consumer);
usleep(1000000);
for (int i = 0; i < N_TESTS; i++) {
usleep(1000);
int64_t scheduledAt = (duration_cast<nanoseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())).count();
testQueue.push(scheduledAt);
}
usleep(1000000);
return 0;
}
编译标志:
g++ -std=c++0x -O3 -Wall -c -fmessage-length=0 -march=native -mtune=native -pthread -MMD -MP -MF"src/TestProject.d" -MT"src/TestProject.d" -o "src/TestProject.o" "../src/TestProject.cpp"
g++ -pthread -o "TestProject" ./src/TestProject.o -lpthread
在我的机器上:RHEL 7.1、gcc 4.8.3、Xeon E5-2690 v3 我收到 290-300 纳秒。
- 我的测试应用程序有多好?我是否正确测量了“spsc_queue”延迟?
- 当前行业将数据从一个线程传递到另一个线程的最佳时间是什么时候?
- 使用 boost spsc_queue 将数据从一个线程移动到另一个线程是不是不错的选择?
- 你能推荐一些比 spsc_queue 更快的东西吗?
- 你能写一段代码来更快地完成相同的工作吗?
upd: 需要队列机制。如果第一个线程每 1000 纳秒产生一次数据,但第二个线程花费 10 000 纳秒来处理单个项目,我需要在短时间内“排队”几个项目。但我的“队列”永远不会“太大”。固定大小的短环形缓冲区就足够了。
upd2 所以简而言之,问题是——最快的单生产者单消费者队列是什么(最有可能基于固定大小的环形缓冲区)?我正在使用 boost spsc_queue,我实现了约 300 ns 的延迟,您能建议更快的方法吗?
upd3 在 java 世界中,有一个能达到 50 ns 延迟的破坏者 https://code.google.com/p/disruptor/wiki/PerformanceResults 我们在 c++ 中是否有具有相同 50 ns 延迟的东西?
【问题讨论】:
-
通常最快的数据传递方式是为每个数据块使用一个线程。也就是说,只使用数据中存在的并行性。
-
在您的基准测试中,消费者线程的启动可能包含在测量的延迟中。最好等到线程开始。平均值也容易受到尖峰的影响。存储每个测量的延迟并在测试后输出它们以手动检查任何模式。
-
我更新了示例 - 添加了 usleep 以确保消费者线程已准备好。将所有值打印到控制台。我的所有结果仍然有效且相同。
-
我猜你知道你实际上并没有从一个线程移动(例如:复制位)任何东西到另一个线程?这只是您感兴趣的消费者的同步/通知延迟?那么您的问题是关于最小化跨线程通知延迟吗?
-
我会调整您的测试,而不是使用单独的时间戳数组,只需将时间戳推入队列,然后当您弹出另一侧时,您就可以直接知道该条目的延迟。 . 这将是消费者拿起生产者生产的东西所需的最短时间......
标签: c++ multithreading performance boost lock-free