5#include <fhsim/simobject/ISimObjectCreator.h>
28inline int ReadNumThreads(ISimObjectCreator* creator)
31 creator->GetIntParam(
"NumThreads", &numThreads, numThreads);
33 const std::string message =
"NumThreads = " + std::to_string(numThreads) +
" is negative; expected 0 (OpenMP's default), 1 (serial) or more.";
34 creator->ReportParameterError(
"NumThreads", message);
35 throw std::invalid_argument(message);
39 numThreads = omp_get_max_threads();
43 return std::max(numThreads, 1);
47inline int ChunkBegin(
const int count,
const int chunk,
const int chunks)
49 return count * chunk / chunks;
61template <
class UpdateNodes,
class AddForces>
62void SumForcesInChunks(
const int chunks,
const int numNodes, std::vector<double>& buffers,
double*
const nodeForce, UpdateNodes updateNodes, AddForces addForces)
64 const size_t bufferSize = 3 *
static_cast<size_t>(numNodes);
65 std::exception_ptr failure;
67# pragma omp parallel num_threads(chunks)
72 const auto keepFailure = [&failure]() {
74# pragma omp critical(net_threads_failure)
78 failure = std::current_exception();
82 const int first = omp_get_thread_num();
83 const int stride = omp_get_num_threads();
89 for (
int chunk = first; chunk < chunks; chunk += stride)
90 updateNodes(ChunkBegin(numNodes, chunk, chunks), ChunkBegin(numNodes, chunk + 1, chunks));
98 for (
int chunk = first; chunk < chunks; chunk += stride) {
99 double*
const forces = buffers.data() + chunk * bufferSize;
100 std::fill(forces, forces + bufferSize, 0.0);
101 addForces(chunk, chunks, forces);
108 std::rethrow_exception(failure);
109 for (
int chunk = 0; chunk < chunks; chunk++) {
110 const double*
const forces = buffers.data() + chunk * bufferSize;
111 for (
size_t i = 0; i < bufferSize; i++)
112 nodeForce[i] += forces[i];