You can use OpenMP parallel for dynamic schedules or OpenMP tasks. Both can be used to parallelize cases where each iteration requires a different amount of time to complete. Dynamically scheduled:
#pragma omp parallel { Fitter fitter; fitter.init(); #pragma omp for schedule(dynamic,1) for (int i = 0; i < numFits; i++) fitter.fit(..., &results[i]); }
schedule(dynamic,1) forces each thread to perform one iteration at a time, and threads never remain in standby mode if iterations are no longer performed.
With tasks:
#pragma omp parallel { Fitter fitter; fitter.init(); #pragma omp single for (int i = 0; i < numFits; i++) { #pragma omp task fitter.fit(..., &results[i]); } #pragma omp taskwait
Here, one of the threads executes a for loop, which creates 1000 OpenMP tasks. OMP tasks are queued and processed by simple threads. It is somewhat similar to dynamic for loops, but provides more freedom in code constructs (for example, with tasks that you can parallelize with recursive algorithms). The taskwait construct expects all pending tasks to complete. This is implied at the end of the parallel region, so it is really only necessary if more code follows the end of the parallel region.
In both cases, each call to fit() will be executed in a different thread. You must make sure that setting one set of parameters does not affect setting other sets, for example. that fit() is a thread safe method / function. Both cases also require that the fit() runtime far exceeds the overhead of the OpenMP constructs.
The OpenMP job requires a compiler compatible with OpenMP 3.0. This excludes all versions of MS VC ++ (even in VS2012) if you have to develop Windows.
If you want to have only one instance of a locksmith that has ever been initialized for each thread, then you should take a slightly different approach, for example. make the installer global and threadprivate :
#include <omp.h> Fitter fitter; #pragma omp threadprivate(fitter) ... int main() { // Disable dynamic teams omp_set_dynamic(0); // Initialise all fitters once per thread #pragma omp parallel { fitter.init(); } ... #pragma omp parallel { #pragma omp for schedule(dynamic,1) for (int i = 0; i < numFits; i++) fitter.fit(..., &results[i]); } ... return 0; }
Here fitter is a global instance of the fitter class. The omp threadprivate directive tells the compiler to put it in a local thread store, for example. to create a global variable. They persist between different parallel areas. You can also use omp threadprivate local variables on static . They are also saved between different parallel areas (but only in the same function):
#include <omp.h> int main() { // Disable dynamic teams omp_set_dynamic(0); static Fitter fitter; // must be static #pragma omp threadprivate(fitter) // Initialise all fitters once per thread #pragma omp parallel { fitter.init(); } ... #pragma omp parallel { #pragma omp for schedule(dynamic,1) for (int i = 0; i < numFits; i++) fitter.fit(..., &results[i]); } ... return 0; }
Calling omp_set_dynamic(0) disables dynamic commands, that is, each parallel region will always execute as many threads as specified by the OMP_NUM_THREADS environment OMP_NUM_THREADS .