2014-08-29 84 views
0

我想比较不同的无锁队列的性能,因此,我想创建一个单元测试 - 其中包括推/弹出用户定义的预构建对象并从队列中。因此,我想问你几个问题: - 1)如何以简单的方式创建预先构建的对象。像我这样创建一个数组是否会达到目的。 2)我得到一个错误“终止调用后抛出'std :: system_error'实例什么():无效参数中止(核心转储)”。对无锁队列执行简单的单元测试

Thanx提前。

#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; 
} 
+0

我看不出为什么会崩溃 - 尝试添加一些跟踪或使用调试器。你根本没有使用'Data'数组...只是推动和弹出它的指针。对于基准测试来说,可能只是推送连续的数字,并让消费者将它们加起来,在“加入”时获得每线程总计。你也可以在'argc'开始编号,这样编译器就不会有任何期望。我喜欢在我的基准测试中看到工作的证据,只是为了让我知道代码能够达到目的,并且不能在编译时将其优化或完成。 – 2014-08-29 07:47:25

+0

我得到的输出为: - 入队和出队100万个项目:0.145872在抛出'std :: system_error'实例后终止what():无效参数中止(核心转储)。但错误令我担心。此外,在队列中推送数字会对用户定义对象的性能产生同样的影响吗? – user225008 2014-08-29 10:23:16

+0

哦 - 崩溃必须是因为您已经加入了相同的线程ID,您在加入消费者线程时忘记在数组索引中使用'NUM_PROD_THREAD +'。您的用户定义的对象数组在生产/消耗分析期间当前未被使用,即使在main()中的第一行执行之前静态地发生数组元素构造。推一个'int'与推任何类型的指针会花费相似的时间......与少数无锁队列操作相比,做一点点添加不会增加太多。您可以单独分析添加1个线程需要多长时间。 – 2014-08-29 10:35:18

回答

0

只是说明如何使用基准Data元素,虽然这确实测得的时间,这是不理想,但可能不是显著无论是内添加cout

class Data 
{ 
public: 
    Data(long i) : i_(i) {} 
    void dataPrint() {cout << "Hello";} 
private: 
    long i_; 
    double j; 
}; 


Data* dataArray[1000000]; 
for (int i = 0; i < NUM_DATA; ++i) dataArray[i] = new Data(i); 

boost::lockfree::queue<Data*> BoostQueue(1000); 

struct Producer 
{ 
    void operator()() 
    { 
     for(long i=0; i<1000000; i++) 
      BoostQueue.push(dataArray[i]); 
    } 
}; 


struct Consumer 
{ 
    Data *pData; 
    long result_; 
    void operator()() 
    { 
     result_ = 0; 
     while ( BoostQueue.pop(pData)) 
      result_ += pData->i_; 
     std::cout << result_ << '\n'; 
    } 
}; 


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[NUM_PROD_THREAD+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(); 
    for (int i = 0; i < 1000000; ++i) 
     delete dataArray[i]; 
} 
+0

谢谢你的插图。但是,我注意到了两件事,一件是它们在两次执行(前一次和这次执行)的执行时间上差别不大。其次,如果我使用result_ + = pData-> i_改变i_(公开),我得到分段错误 – user225008 2014-09-01 05:51:02

+0

@ user225008:这个想法是做一些非常微不足道的工作,所以它不会更改执行时间,但会最少要说明的是访问队列已经通过指针的对象,因此它指示最少的“真实”工作。对于segfault--你可以将循环和数据从100万减少到10,并且打印('cout')'pData'值被推送和弹出,以确保它成功弹出有效指针。 – 2014-09-01 06:17:38

+0

谢谢! Tony D. – user225008 2014-09-01 06:26:23