These tests are:
[object Object],[object Object]
Both tests call the very same function that implements a long computation. The max parameter controls the number of computations, and nb controls the duration of a single computation, that is quadratic in nb. The threads is as expected the number of threads to use for the computation. The progress parameter toggles the display of the progress bar.
On my platform, system.time( RcppProgress:::test_multithreaded(100, 3000, 4) ) is a good start.
}
There are usually two locations in the c++ code that needs to be modified. The first one is the main loop, typically on the number of jobs or tasks. This loop is a good candidate to be parallelized using OpenMP. I will comment the code corresponding to the tests included with the package.
void test_multithreaded_omp(int max, int nb, int threads , bool display\_progress) {
\#ifdef _OPENMP if ( threads > 0 ) omp_set_num_threads( threads ); REprintf(\"Number of threads=%i\n\", omp_get_max_threads()); \#endif
Progress p(max, display_progress); // create the progress monitor #pragma omp parallel for schedule(dynamic) for (int i = 0; i < max; ++i) { if ( ! p.is_aborted() ) { // the only way to exit an OpenMP loop long_computation(nb); p.increment(); // update the progress } } }
Here we create a Progress object with the number of tasks to perform, then
before performing a task we test for abortion (p.is_aborted()), because we can not exit an
OpenMP loop the usual way, suing a break for example, then
when after the computation, we increment the progress monitor.
Then let us look at the computation function (that is completely useless) :
void long_computation(int nb) { double sum = 0; for (int i = 0; i < nb; ++i) { if ( Progress::check_abort() ) // check for user abort return; for (int j = 0; j < nb; ++j) { sum += Rf_dlnorm(i+j, 0.0, 1.0, 0); } } } }
Here the only interesting line is the Progress::check_abort() call.
If called from the master thread, it will check for user interruption, and if needed
set the abort status code.
When called from another thread it will just check the status.
So all the art is to decide where to put his call: it should not be called not too often
or not frequently enough.
As a rule of thumb it should be called roughly evevry second.
}
Please note that we provide the RcppProgressExample example package along with this package,
located in the examples directory of the installed package.
Here are the steps to use RcppProgress in a new package:
[object Object],[object Object],[object Object],[object Object] }