diff --git a/Framework/MDAlgorithms/src/MDNormSCD.cpp b/Framework/MDAlgorithms/src/MDNormSCD.cpp index 866d15d23ab3ebe6334938397390247274069f09..ed8155a2690f7f1acf8d728d4c875647ba9fc7e6 100644 --- a/Framework/MDAlgorithms/src/MDNormSCD.cpp +++ b/Framework/MDAlgorithms/src/MDNormSCD.cpp @@ -363,6 +363,16 @@ void MDNormSCD::cacheDimensionXValues() { } } +namespace { +template <typename T, typename BinaryOp> +void AtomicOp(std::atomic<T> &f, T d, BinaryOp _Op) { + T old = f.load(); + T desired = _Op(old, d); + while (!f.compare_exchange_weak(old, desired)) + desired = _Op(old, d); +} +} // namespace + /** * Computed the normalization for the input workspace. Results are stored in * m_normWS @@ -402,6 +412,8 @@ void MDNormSCD::calculateNormalization( const detid2index_map solidAngDetToIdx = solidAngleWS->getDetectorIDToWorkspaceIndexMap(); + std::vector<std::atomic<signal_t>> signalArray(m_normWS->getNPoints()); + auto prog = make_unique<API::Progress>(this, 0.3, 1.0, ndets); PARALLEL_FOR_IF(Kernel::threadSafe(*integrFlux)) for (int64_t i = 0; i < ndets; i++) { @@ -474,18 +486,16 @@ void MDNormSCD::calculateNormalization( // index of the current intersection size_t k = static_cast<size_t>(std::distance(intersectionsBegin, it)); // signal = integral between two consecutive intersections - double signal = (yValues[k] - yValues[k - 1]) * solid; - - PARALLEL_CRITICAL(updateMD) { - signal += m_normWS->getSignalAt(linIndex); - m_normWS->setSignalAt(linIndex, signal); - } + signal_t signal = (yValues[k] - yValues[k - 1]) * solid; + AtomicOp(signalArray[linIndex], signal, std::plus<signal_t>()); } prog->report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION + std::copy(signalArray.cbegin(), signalArray.cend(), + m_normWS->getSignalArray()); } /**