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

Is it possible to use threads if they have to write on the same vector

本文关键字:线程 是否 可以使 向量 如果      更新时间:2023-10-16

我必须用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();

可悲的是,我没有精通线程。

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

正如马丁·邦纳(Martin Bonner)在注释中提到的那样,一种方法是让每个线程分开保持自己的统计信息,并在末尾结合各种线程结果。

另一种方法是使用原子变量。如果count数组保存std::atomic<int>而不是普通int(或实际计数数据类型实际是),则使用一个更改的代码可以正常工作:替换

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

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

++count[dist1 + s*dist2];

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

好吧,如果您在计算后使用向量插入结果,则需要的是确保一次只有一个线程在一次向量上执行插入操作。由于插入操作不是很复杂,因此在插入时阻止其他线程没有时间惩罚。

最好的方法是使用Mutex对象;

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();
    }
}