2014-08-29 40 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