Boost logo

Boost Users :

Subject: Re: [Boost-users] [Threads] and OpenMP
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2014-10-01 07:03:48


On 30 Sep 2014 at 11:24, Stephan Menzel wrote:

> I would like to ask around about a strategy on how to tacke the following
> threading problem:
>
> I am maintaining a boost intensive portable C++ client-server application
> and recently have included a highly complex 3rd party algorithm into my
> application that does CPU intense stuff. Long running stuff. Often in the
> range of days. While at the same time being heavy in OpenMP usage. Now of
> course requirements are that the user has to be able to cancel this.

That's a terrible design. If you ever have to lifetime manage OpenMP
code, you shouldn't be using OpenMP.

> The algorithm runs in a boost threads controlled background thread. Now I
> began to place interruption points throughout the 3rd party code but soon
> had to realize that a lot of CPU time is being handled in OpenMP threaded
> code regions.
>
> So the question is: How can I more or less gracefully shut this down? How
> do interruption points work in an omp parallel for loop? Do I have a chance
> at all?
>
> My constraints here are a bit forgiving. Given the complexity of the 3rd
> party code I have already accepted the notion that this is gonna be a
> memleak monster. Luckily, there's no disk or other hardware access so I'm
> ready to live with a certain amount of mem not being cleaned up. Yet the
> backend thread communicates with the spawning class by calling a mutexed
> callback when it's ready so the user knows it's cancelled. This is
> protected by a boost mutex as well. And juding from the horrible threading
> "clogs" that I observed in my first trials I suppose this is gonna be a
> problem as well.
>
> And input is appreciated. And yes, I am aware that this is gonna be an ugly
> mess.

Obviously, you should refactor the code to not misuse OpenMP this way
- a much better approach is to use ASIO as a closure executor, and
refactor all OpenMP constructs to dispatch work items to ASIO instead
(this is all OpenMP does internally anyway to an ASIO equivalent).
But given you can't do that, I'd suggest a very simple solution:
create a global variable std::atomic<bool> called
termination_requested or something. In each of your OpenMP
constructs, check if it is true, and if so bail out - if your code is
exception safe, throwing an exception is one way.

Rinse and repeat until you've found all code paths. One evil way
might be to hijack all OpenMP synchronisation points by using the C
preprocessor to insert code at certain OpenMP constructs. Or you
could write a binary patcher to patch all internal _omp_* functions
to call some termination check routine. On POSIX only you can even
simply send signals to all worker threads, and get the signal handler
to bail out for you.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ 
http://ie.linkedin.com/in/nialldouglas/



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net