2015-02-09 29 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

相关问题