2015-02-09 30 views
1

我正在用C++編寫Monte Carlo程序,並且使用std :: thread劃分要在線程之間跟蹤的歷史數量。然而,這是我第一次嘗試多線程,我遇到了這樣一個問題,即這個簡化的代碼應該讓我能夠展示,希望我能從本網站的讀者那裏得到一些建議。在這個簡化的問題中,我調用了Summation函數,該函數用2個線程產生1X5維的隨機數字數組。當線程返回它們的值(由於它是一個全局變量而沒有真正返回)時,主程序就有兩個五維數組,每個數組對應一個不同的線程。我想將兩個數組合併成一個數組,最後一個數組中的元素對應於兩個數組中由不同線程產生的相同元素的總和。不幸的是,每個線程的數組都有相同的名稱,所以我不能簡單地將兩個不同的數組添加在一起。建議使用什麼方法將兩個1X5維數組合併成一個求和數組,其元素對應於每個線程中相同元素的總和?使用std :: thread將多個線程的數組組合在一起使用std :: thread

#include <iostream> 
#include <vector> 
#include <thread> 
#include <mutex> 
#include <cassert> 
#include "boost/multi_array.hpp" 

std::vector<float> Array; 
std::mutex Array_mutex; 

void Summation(int sample_size) 
{ 
    std::lock_guard<std::mutex> guard(Array_mutex); 
    for(int i = 0; i < sample_size; i++) 
    { 
     Array.push_back(rand() % 10 + 1); 
    } 
    std::cout << "\n"; 
} 

int main(int argc, const char * argv[]) { 
    int sample_size = 10; 
    int Num_Threads = 2; 
    int number_count = sample_size/Num_Threads; 
    srand(time(NULL)); 
    std::vector<std::thread> Threads; 
    for(int i = 0; i < Num_Threads; i++) 
    { 
     Threads.push_back(std::thread(Summation,number_count)); 
    } 

    for(int i = 0; i < Num_Threads; i++) 
    { 
     Threads[i].join(); 
    } 

    // - I would like to combine the arrays produced from each thread into a 
    // single array, where each element in the final array is the sum of 
    // the identical element in the array from each thread 

    // i.e. Element 1(final) = Element 1(thread 1) + Element 1(thread2) 
    //  Element 2(final) = Element 2(thread 1) + Element 2(thread2) 
    //  Element 3(final) = Element 3(thread 1) + Element 3(thread2) 

    return 0; 
} 
+1

有兩件事情:讓每一個步驟做一點點的計算,所以一個線程會做1到10,另一個11到20,等等。如果矢量是以固定大小創建的(或者如果你使用'std :: array'),那麼你不需要鎖。另一件事是,只有一次初始化隨機數發生器*。 – 2015-02-09 18:39:37

+0

另外,你沒有*多個數組(或向量)在代碼中「結合」,所有線程都會寫入同一個數組。事實上,無視我先前評論的第一部分,因爲你的問題是另一個問題,那就是你沒有多個向量,只有一個向量。 – 2015-02-09 18:42:59

+0

O.K.,這是改變我對輸出的理解的好信息。如果它是同一個數組,那麼這意味着來自一個線程的數據會覆蓋第二個線程產生的數據,這就是爲什麼當我使用std :: cout命令打印它們時會得到兩個數組,但實際上它是相同的陣列/內存插槽用覆蓋數據打印兩次。如果這是真的,那麼我怎樣才能讓每個線程創建一個可以在另一個線程或主程序中組合的獨立數組? – Jon 2015-02-09 18:58:58

回答

1

如果你想每個線程一個載體,你實際上需要有每個線程一個載體。像矢量矢量一樣。

對於簡單和天真的解決方案,像

#include <iostream> 
#include <array> 
#include <random> 
#include <thread> 

void generate(const size_t size, std::array<float>& values) 
{ 
    // Pseudo-random number generation stuff 
    std::random_device rd; 
    std::default_random_engine e1(rd()); 
    std::uniform_int_distribution<float> uniform_dist(1, 10); 

    // Generate some values and add the array 
    for (size_t i = 0; i < size; ++i) 
     values[i] = uniform_dist(el); 
} 

int main() 
{ 
    constexpr size_t number_values = 10; 
    constexpr size_t number_threads = 2; 

    // An array of arrays, one sub-array per thread 
    std::array<std::array<float, number_values>, number_threads> 
     values; 

    // An array of threads 
    std::array<std::thread, number_threads> threads; 

    // Create threads 
    for (size_t i = 0; i < number_threads; ++i) 
     threads[i] = std::thread(generate, number_values, std::ref(values[i])); 

    // Wait for threads to finish 
    for (size_t i = 0; i < number_threads; ++i) 
     threads[i].join(); 

    // Now "combine" the values into a single array 
    std::array<float, number_values> totals; 
    for (size_t i = 0; i < number_values; ++i) 
    { 
     for (size_t j = 0; j < number_threads; ++j) 
      totals[i] += values[j][i]; 
    } 

    // Print the values 
    for (const size_t i; i < number_values; ++i) 
     std::cout << "Value #" << (i + 1) << " = " << totals[i] << '\n'; 
} 

注意,代碼是未經測試,甚至不會編譯,但在理論上應工作。 :)

+0

謝謝你的例子,一張圖片描繪了千言萬語! ;-) – Jon 2015-02-09 19:04:02

+0

除少數問題外,代碼工作得很好。唯一的問題是值數組必須在函數調用中分配。不幸的是,我的問題需要動態數組分配,因爲我不知道在用戶定義的問題中將使用多少個蒙特卡羅檢測器。我嘗試了所有我能想到的與矢量和點並沒有任何工作。最後,我給出了分配陣列的正確方法,以確保用戶可以根據需要定義多個檢測器。感謝這個例子的幫助。 – Jon 2015-02-10 03:40:28

相關問題