[bos #42217][EDF 28921] Horseshoe with bodyfitting.

Fixed infinite loop of creating threads that caused crash on parallel computing for a case when number of hexaedrons is less than number of threads.
This commit is contained in:
Konstantin Leontev 2024-07-17 10:23:05 +01:00
parent 066445b0e6
commit 4b39d980ce

View File

@ -3634,24 +3634,66 @@ namespace
// Implement parallel computation of Hexa with c++ thread implementation // Implement parallel computation of Hexa with c++ thread implementation
template<typename Iterator, class Function> template<typename Iterator, class Function>
void parallel_for(const Iterator& first, const Iterator& last, Function&& f, const int nthreads = 1) void parallel_for(const Iterator& first, const Iterator& last, Function&& f, const unsigned int nthreads = 1)
{ {
const unsigned int group = ((last-first))/std::abs(nthreads); MESSAGE("Start parallel computation of Hexa with c++ threads...");
assert(nthreads > 0);
const unsigned int numTasksTotal = last - first;
std::vector<std::thread> threads; std::vector<std::thread> threads;
threads.reserve(nthreads);
Iterator it = first; Iterator it = first;
for (; it < last-group; it += group) {
// to create a thread
// Pass iterators by value and the function by reference!
auto lambda = [=,&f](){ std::for_each(it, std::min(it+group, last), f);};
// stack the threads MESSAGE("Number of elements to compute: " << numTasksTotal << "; num of threads: " << nthreads);
threads.push_back( std::thread( lambda ) );
// Distribute tasks among threads
if (numTasksTotal <= nthreads)
{
// A simple case - just one task executed in one thread.
// TODO: check if it's faster to do it sequentially
threads.reserve(numTasksTotal);
for (; it < last; ++it)
{
threads.emplace_back(f, std::ref(*it));
}
}
else
{
// Calculate how to distribute elements among threads evenly
const unsigned int numTasksInThread = numTasksTotal / nthreads;
MESSAGE("Number of tasks in thread: " << numTasksInThread);
// Store the numbers of tasks per thread
std::vector<unsigned int> distTasksInThreads(nthreads, numTasksInThread);
// Distribute a remainder among saved numbers
const unsigned int remainder = numTasksTotal % nthreads;
MESSAGE("Remainder of tasks " << remainder << " will be evenly distributed among threads");
for (unsigned int i = 0; i < remainder; ++i)
{
++distTasksInThreads[i];
} }
std::for_each(it, last, f); // last steps while we wait for other threads // Create threads for each number of tasks
std::for_each(threads.begin(), threads.end(), [](std::thread& x){x.join();}); threads.reserve(nthreads);
for (const auto i : distTasksInThreads)
{
Iterator curLast = it + i;
// Pass iterators by value and the function by reference!
auto lambda = [=,&f](){ std::for_each(it, curLast, f); };
// Create a thread
threads.emplace_back(lambda);
// Advance iterator to the next step
it = curLast;
}
}
std::for_each(threads.begin(), threads.end(), [](std::thread& x){ x.join(); });
MESSAGE("Parallel computation was finished successfully");
} }
//================================================================================ //================================================================================
/*! /*!