如果必须在同一个向量上写入,是否可以使用线程

时间:2016-12-12 13:32:04

标签: c++ multithreading c++11

我必须用SDE解决热量方程。 程序运行正常,但速度很慢。

简而言之:我编写了一个程序,可以在矢量上随机设置许多粒子并将它们移动一段时间。 在时间t之后,计算每个网格箱中的所有粒子并将该数字保存在计数向量中。现在我必须做runs = 1000才能获得好结果。 (这些函数属于一个类)。

void makeruns(const int runs){
  for(int i=0; i<runs; ++i){
      setandmove();
  }
}

void setandmove(){
    for(int t=0; t<timesteps; ++t){
       //set new particles and move particles on the grid
    }
    //Endposition is saved in the list Y_omega

    //count number of points in bins
    for(auto it=Y_omega.begin(); it!=Y_omega.end(); ++it){
        double valf = it->first;
        double vals = it->second;
        auto it_f =    std::lower_bound(intervall.begin(),intervall.end(),valf, [](auto P, auto V) -> bool {return P< V;});
        auto it_s = std::lower_bound(intervall.begin(),intervall.end(),vals, [](auto P, auto V) -> bool {return P < V;});

        int dist1 = std::distance(intervall.begin(),it_f);
        int dist2 = std::distance(intervall.begin(),it_s);

        count.at(dist1 + s*dist2)=count.at(dist1 + s*dist2) + 1;
    }
    Y_omega.clear();
}

是否有可能制作线程,至少对于第一部分,或者当他们在向量count

上写字时它们会发生碰撞
std::thread t1(makeruns, 250);
std::thread t2(makeruns, 250);
std::thread t3(makeruns, 250); 
std::thread t4(makeruns, 250);

t4.join();
t3.join();
t2.join();
t1.join();

可悲的是,我并不精通线程。

2 个答案:

答案 0 :(得分:3)

如果多个线程要读取写入相同的数据位置,则代码必须同步这些访问。否则行为未定义。

正如Martin Bonner在一篇文章中提到的,一种方法是让每个线程分别保留自己的统计信息,并在最后组合各种线程结果。

另一种方法是使用原子变量。如果count数组包含std::atomic<int>而不是普通int(或者您的计数数据类型实际上是什么),那么编写的代码(只需更改一次)就可以正常工作:replace < / p>

count.at(dist1 + s*dist2)=count.at(dist1 + s*dist2) + 1;

++count.at(dist1 + s*dist2);

++count[dist1 + s*dist2];

选择采用哪种方法取决于正在处理的数据的性质。

答案 1 :(得分:1)

如果您在每次计算后使用向量插入结果,那么您需要确保一次只有一个线程对向量执行插入操作。由于插入操作不是很复杂,插入时阻塞其他线程不会有时间损失。

最好的方法是使用互斥对象;

std::mutex m; // may be a global object or may be shared by a using a pointer.
Vector counting_vector; //some vector object for keeping result of each computation.

void threadWorker(int count){
     //here
    //create vector that will be used for set and move operation. Each thread will have it's own vector.
    while(count-->0){

        //perform the set and move operation on the vector;
        result=;/*the computed result*/
        m.lock();
        //code between lock() and unlock() won't run concurrently.
        counting_vector.insert(result);//insert or push_back into the vector
        m.unlock();

    }

}