From 9ebd889a05a54faca2a5b6593a33add60cc6b1a9 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (l)" <j.wuttke@fz-juelich.de>
Date: Wed, 28 Oct 2015 09:53:10 +0100
Subject: [PATCH] replace OpenMP by C++ threads; this introduces an OS
 dependency (pthread) into lib/CmaeLists.txt.

---
 pub/CMakeLists.txt | 15 +-----------
 pub/lib/fit.cpp    | 57 ++++++++++++++++++++++++++++++----------------
 2 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/pub/CMakeLists.txt b/pub/CMakeLists.txt
index a992b214..3bde8633 100644
--- a/pub/CMakeLists.txt
+++ b/pub/CMakeLists.txt
@@ -19,22 +19,9 @@ enable_testing()
 #option(FRIDA_MAN "Build a user manual" OFF)
 #option(BUILD_DEBIAN "Build a debian package" OFF)
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -pedantic -Wall -Wno-sign-compare -Wno-unused-result -Wno-parentheses -Werror")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -pedantic -Wall -Wno-sign-compare -Wno-unused-result -Wno-parentheses  -Wno-unknown-pragmas -Werror")
 # to use C99 _Complex, add -fext-numeric-literals to CXX_FLAGS
 
-option (openmp "Enable multithreading with OpenMP" ON)
-if (openmp)
-    find_package (OpenMP)
-    if (OPENMP_FOUND)
-        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
-        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
-    endif()
-    message( STATUS "OpenMP: on" )
-else()
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas")
-    message( STATUS "OpenMP: off" )
-endif()
-
 find_package(Boost REQUIRED) # used header-only modules: format algorithm
 find_package(BISON REQUIRED)
 find_package(FLEX REQUIRED)
diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp
index 5c5ff649..42f87cdd 100644
--- a/pub/lib/fit.cpp
+++ b/pub/lib/fit.cpp
@@ -9,9 +9,9 @@
 
 #include "defs.hpp"
 
+#include <functional>
 #include <thread>
 #include <boost/format.hpp>
-#include <omp.h>
 #include <lmmin.h>
 
 #include "../readplus/ask.hpp"
@@ -32,6 +32,26 @@ namespace NCurveFit {
     void fit_global( POlc fc, ROld fd, int k, const lm_control_struct& control );
 }
 
+void conditionally_parallel_for(
+    bool condition, int niter,
+    const std::function<void(int)>& exec, const std::function<void(int)>& report )
+{
+    if ( condition ) {
+        vector<std::thread> workers;
+        for ( int i=0; i<niter; ++i ) {
+            workers.push_back( std::thread(exec, i) );
+        }
+        for ( int i=0; i<niter; ++i ) {
+            workers[i].join();
+            report(i);
+        }
+    } else {
+        for ( int i=0; i<niter; ++i ) {
+            exec(i);
+            report(i);
+        }
+    }
+}
 
 //**************************************************************************************************
 //*  Fit tuning parameters
@@ -212,7 +232,7 @@ string NCurveFit::fit_one_spec( POlc fc, ROld fd, int k, int j, const lm_control
 
         // Levenberg-Marquardt routine from library lmfit:
 
-        data.timeout = time(nullptr) + omp_get_num_threads()*maxtime;
+        data.timeout = time(nullptr) + std::thread::hardware_concurrency()*maxtime;
 
         lm_status_struct status;
         lmmin( npfree, &(Par[0]), nd, &data, fit_evaluate, &control, &status );
@@ -304,14 +324,15 @@ static void fit_evaluate_glo( const double* par, int m_dat, const void *data,
             throw S("inconsistent number of free parameters");
 
         bool want_error = wt==COlc::_VAR || wt==COlc::_VARC;
-#pragma omp parallel for // if ( !NCurveFit::verbosity )
-        for( int jj=0; jj<mydata->J2J.size(); ++jj ) {
-            compute_residues(
-                fvec, mydata->Offset[jj], mydata->J2J[jj], fd->VS(mydata->J2J[jj]),
-                fc->eval_curve( fd->VS(mydata->J2J[jj])->x, mydata->k, mydata->J2J[jj],
-                                want_error ),
-                wt );
-        }
+        conditionally_parallel_for (
+            !NCurveFit::verbosity, mydata->J2J.size(),
+            [&](int jj) -> void {
+                compute_residues(
+                    fvec, mydata->Offset[jj], mydata->J2J[jj], fd->VS(mydata->J2J[jj]),
+                    fc->eval_curve( fd->VS(mydata->J2J[jj])->x, mydata->k, mydata->J2J[jj],
+                                    want_error ),
+                    wt ); },
+            [&](int jj) -> void {} );
     } catch ( string& s ) {
         cout << "\n" << s << "\n";
         *userbreak = -1;
@@ -504,16 +525,12 @@ void NCurveFit::fit( bool _allow_slow_conv )
                 if ( !fc->VC(j)->frozen )
                     J.push_back( j );
             vector<string> out(J.size(), "");
-            vector<std::thread> workers;
-            for ( int jj=0; jj<J.size(); ++jj ) {
-                workers.push_back( std::thread([&](int _jj) -> void {
-                            out[_jj] = fit_one_spec( fc, fd, fiter.k(), J[_jj], control ) +
-                                "\n"; }, jj ) );
-            }
-            for ( int jj=0; jj<J.size(); ++jj ) {
-                workers[jj].join();
-                cout << out[jj];
-            }
+            conditionally_parallel_for(
+                !NCurveFit::verbosity, J.size(),
+                [&](int _jj) -> void {
+                    out[_jj] = fit_one_spec( fc, fd, fiter.k(), J[_jj], control ) + "\n"; },
+                [&](int _jj) -> void {
+                    cout << out[_jj]; } );
         } // fit mode
     } // k
 }
-- 
GitLab