I have a C++ program that has a double for loop that I'd like to parallelize using opeMP. It is simple (a polynomial product) of varying length (between 100 and 8000 coefficients) and the function is called millions of times per execution.

I have the parallel pragma around the outer loop and the for pragma just below the parallel pragma. I have found that if the number of elements is big, near 8000, the execution time is good, lower than without parallelization. However, for small number of coefficients, the performance is degraded, and the parallel version is slower than the serial one.

I suppose it is due to the creation/destruction of parallel threads every time the function is called. I can limit the creation of threads with an if in the pragma, so it is only parallelized for big polynomials, but I was wondering if there is a way to avoid creation/destruction of the threads, so I could create them once and leave them "waiting" between calls, so they would be ready when needed. That function is the only one I'm parallelizing and I cannot move the parallelization to the caller function.

I'm using g++.

-

The Intel Compiler stack uses KMP_BLOCKTIME=<time in milliseconds, infinite> to set the time that the threads wait to go to sleep after the end of the loop (or infinite). I don't know if GCC supports this. You might trying setting OMP_WAIT_POLICY=active to force the threads to always spin. This will keep the threads running after the end of the loop, but it might also impact your performance between OpenMP calls.

-
Thanks for the answer, I'll try it! With this configuration, threads won't be closed even after the parallel block? – siritinga Feb 21 '14 at 22:28
That's my understanding, though it's been a long time since I played with it. – Bill Barth Feb 22 '14 at 1:44

A more involved solution is to lift the parallel region above this routine and wrap the code you don't want to be parallel with a single/master clause. The advantage here is that you might figure out how to increase the amount of threading in your code, which is good in the battle against Amdahl's Law. On the other hand, doing this might be rather involved and not worth much benefit relative to the solutions discussed already.

-
Thank you Jeff. Maybe I should have said before that it is a terribly designed software and I have the 'opportunity' to try to fix. It has plenty of global variables used for temporary arrays and data exchange between functions, and lot of overloaded operators so parallelizing it at a higher level is not possible without refactoring the whole application. – siritinga Feb 23 '14 at 10:48
Have you considered just rewriting it from scratch? Sometimes this is not as hard as it looks. – Jeff Feb 23 '14 at 21:44
I would love to but 1) no time to rewrite something that works. 2) No unit/integration/global test to check an alternative implementation. 3) Almost no documentation. 4) It is an implementation of a very theoretical doctorate program that I don't understand. 5) the original author is unavailable. So whatever I could improve is welcome but it is not top priority for my employers :) – siritinga Feb 23 '14 at 23:50
If 2+3, there is no basis for verifying the code and you can implement anything and call it correct. – Jeff Feb 25 '14 at 1:37

I suppose you are looking for using openmp thread pool. I am not sure which runtme implementation you are using but normally you can use omp_set_num_threads(int) to set the thread pool size on initialization. Only if runtime is unable to create a threadpool, then it will create threads dynamically at run time.

But I am not sure how you identified your bottleneck is thread start and stop. I advise you to profile your code to understand where you are actually hitting the bottleneck.

-