Reputation: 1071
I have to solve the heat equation with a SDE. The program runs correctly but it is very slow.
In a short way: i wrote a program, thats sets many particles randomly on a vector and moves them for some timesteps.
After the time t, one counts all particles in each grid bin and saves this number in a counting-vector. Now i have to do runs
=1000 for a good result. (The functions belong to a class).
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();
}
Is it possible to make threads, at least for the first section or will they collide when they write on the vector 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();
Sadly i am not versed in threading.
Upvotes: 1
Views: 198
Reputation: 76245
If multiple threads are going to be reading and writing to the same data locations, the code has to synchronize those accesses. Otherwise the behavior is undefined.
As Martin Bonner mentioned in a note, one way to do that is to have each thread keep its own statistics separately, and combine the various thread results at the end.
Another way to do it is with atomic variables. If the count
array holds std::atomic<int>
instead of plain int
(or whatever your count data type actually is), then the code as written, with one change, will work just fine: replace
count.at(dist1 + s*dist2)=count.at(dist1 + s*dist2) + 1;
with
++count.at(dist1 + s*dist2);
or
++count[dist1 + s*dist2];
The choice of which approach to take depends intimately on the nature of the data that's being processed.
Upvotes: 4
Reputation: 1144
Well if you are using a vector to insert result after each calculation, what you need is to make sure that only one thread performs insertion operation on the vector at a time. Since insertion operation is not very complex, blocking other threads while inserting won't have time penalty.
The best way would be to use a mutex object;
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();
}
}
Upvotes: 1