【发布时间】:2014-08-29 07:00:23
【问题描述】:
我正在尝试比较不同无锁队列的性能,因此,我想创建一个单元测试 - 其中包括将用户定义的预构建对象推入和弹出队列。因此,我想问你几个问题:- 1)如何以简单的方式创建预建对象。像我一样创建一个数组是否可以达到目的。 2) 我收到一个错误“在抛出 'std::system_error' what() 的实例后调用终止:无效参数已中止(核心转储)”。
提前感谢。
#include <cstdlib>
#include <stdio.h>
#include <string>
#include <chrono>
#include <iostream>
#include <ctime>
#include <atomic>
#include <thread>
#include <boost/lockfree/queue.hpp>
using namespace std;
const long NUM_DATA = 10;
const int NUM_PROD_THREAD = 2;
const int NUM_CONSUM_THREAD = 2;
const long NUM_ITEM = 1000000;
class Data
{
public:
Data(){}
void dataPrint() {cout << "Hello";}
private:
long i;
double j;
};
Data *DataArray = new Data[NUM_DATA];
boost::lockfree::queue<Data*> BoostQueue(1000);
struct Producer
{
void operator()()
{
for(long i=0; i<1000000; i++)
BoostQueue.push( DataArray );
}
};
struct Consumer
{
Data *pData;
void operator()()
{
while ( BoostQueue.pop( pData ) ) ;
}
};
int main(int argc, char** argv)
{
std::thread thrd [NUM_PROD_THREAD + NUM_CONSUM_THREAD];
std::chrono::duration<double> elapsed_seconds;
auto start = std::chrono::high_resolution_clock::now();
for ( int i = 0; i < NUM_PROD_THREAD; i++ )
{
thrd[i] = std::thread{ Producer() };
}
for ( int i = 0; i < NUM_CONSUM_THREAD; i++ )
{
thrd[NUM_PROD_THREAD+i] = std::thread{Consumer()};
}
for ( int i = 0; i < NUM_CONSUM_THREAD; i++ )
{
thrd[i].join();
}
auto end = std::chrono::high_resolution_clock::now();
elapsed_seconds = end - start;
std::cout << "Enqueue and Dequeue 1 million item in:" << elapsed_seconds.count() << std::endl;
for ( int i = 0; i < NUM_PROD_THREAD; i++ )
{
thrd[i].join();
}
return 0;
}
【问题讨论】:
-
我不明白您为什么会崩溃 - 尝试添加一些跟踪或使用调试器。您根本没有使用
Data数组......只是推送和弹出指向它的指针。对于基准测试,也许只需推送连续的数字并让消费者将它们相加,当您join时获得每个线程的总数。您也可以从argc开始数字,这样编译器就不会有任何期望。我喜欢在我的基准测试中看到工作的证据,这样我就知道代码做了预期的事情,并且不能在编译时被优化掉或完成。 -
我得到的输出如下:- 在抛出 'std::system_error' what() 的实例后调用入队和出队 100 万个项目:0.145872 终止调用:无效参数中止(核心转储)。但这个错误让我担心。另外,在队列中推送数字对性能的影响是否与自定义对象一样?
-
哦 - 崩溃一定是因为您已经加入了相同的线程 id...您在加入消费者线程时忘记在数组索引上使用
NUM_PROD_THREAD+。您的用户定义对象数组当前未在生产/消费分析期间使用,即使数组元素构造在main()的第一行执行之前静态发生。推送int与推送任何类型的指针将花费相似的时间……与无锁队列操作相比,做一点添加不会增加太多。您可以单独分析添加 1 个线程所需的时间。 -
谢谢!我花了一整天的时间试图消除这个错误:D。最后一个问题。我想我明白你关于推动 int 与指针的说法。但是如果我想将预先构建的对象推送到队列中。我怎样才能做到这一点?我想在不依赖容器的情况下做到这一点。更简单的方法会有所帮助。
-
不客气。好吧,如果生产者推送一个指向对象的指针,那么消费者可以像你一样获取指针......你只是没有碰巧使用它并在定时代码之外进行所有创建,这就是我说你的原因还不如使用
ints 进行基准测试。在您的真实应用程序中,只需在pushing 指向它们之前将对象一一对应地new,然后当消费者弹出指向该对象的指针时,它可以在调用delete之前处理该对象。是这个意思吗?
标签: c++ unit-testing