question about qthread_disable_worker

8 views
Skip to first unread message

Dragos

unread,
Jan 2, 2014, 6:37:14 PM1/2/14
to qthr...@googlegroups.com
Hello all,

I am trying to figure out the use of the qthread_disable_worker API call. I expected this call to stop the mail loop of the worker, but, looking at the output of the "top" command, this does not happen. Do I need to do something else for the disabling to take place? 

I was hoping to use this call to pause qthreads while I call into another parallel library which would otherwise perform poorly because qthreads holds the CPU hostage :) . Is there another way to achieve the same result? I cannot finalize and reinitialize qthreads because that would cause problems with FEBs that I am using before and after the library call.

Thank you for your help and Happy New Year!

Kyle Wheeler

unread,
Jan 2, 2014, 10:52:01 PM1/2/14
to qthr...@googlegroups.com
Hi Dragos,

No, the qthread_disable_worker call really just tells workers to stop scheduling tasks - they then poll waiting to be re-enabled. The purpose of the call was to control the use of shared resources, like cache space, where it might be advantageous to toggle how many pthreads are scheduling tasks in a very lightweight way.

Generally, getting two threading/tasking runtimes to work together in a non-combative way is a nontrivial challenge. There are a couple ideas I've had for doing it, but none that have ever risen to the top of the priority list: you could try adding a pthread mutex (or a pthread_cond) to the scheduling loop to put a hard-stop on the disabled worker thread. That's effective, but expensive (I believe Dylan explored this kind of thing in the context of a different project), and has the potential for creating deadlock (so you have to be very careful about things like shutdown). Another option is to use the nice() command to lower the execution priority of the worker threads, so that they aren't so combative with the other tasking system, and combine that with regular yielding instead of spinning. It's not perfect, and might be expensive (since it's an OS call), but might be good enough to get you what you want.

In any event, shutting down (or disabling) all the worker threads in a large system (where large is >8 cores), only to re-enable them later, is going to be a non-trivial expense. This other tasking system has to be REALLY important to justify the cost.

Hope that helps...

~Kyle


--
You received this message because you are subscribed to the Google Groups "qthreads" group.
To unsubscribe from this group and stop receiving emails from it, send an email to qthreads+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Ahh! Arrogance and stupidity in the same package, how efficient of you!
--Londo Molari

Dragoș Sbîrlea

unread,
Jan 3, 2014, 4:19:23 PM1/3/14
to qthr...@googlegroups.com
Kyle, thank you very much for the fast answer.

I am not too worried about the performance of stopping the threads
since I only need to do this once per execution of the program which
is expected to take at least on the order of tens of minutes. The
other tasking system is actually the library version of an integer
linear programming solver which really needs to run using parallelism,
otherwise it will take a long time. There is no task either queued or
running on qthreads at that point, but there will be some after the
solver finishes.

I was hoping to do this without modifying Qthreads itself, since this
would lead to complications about building and distributing the
application. The only solution I see right now is to save all FEBs
somewhere, finalize qthreads, wait for the solver to finish and then
initialize qthreads again and re-insert FEBs corresponding to the old
ones.

An alternative approach would be to selectively initialize just the
FEB part of qthreads (without starting the workers). Is there some way
to do this without modifying the qthreads code?
Best,
Dragos

Kyle Wheeler

unread,
Jan 3, 2014, 5:27:11 PM1/3/14
to qthr...@googlegroups.com
Hi Dragos,

The FEBs issue, I think, depends on what you need to be saved. If all you need is to remember FEB state, then using syncvar_t's might do the trick for you, because they remember full/empty state as part of the data format, so there's no real "saving" that needs to be done: they will persist through a shutdown/restart. However, if you need to remember "these three tasks were waiting on this FEB", then things will get more hairy.

Unfortunately, no, there isn't a way to initialize "just the FEBs" in Qthreads - it never made any sense to split that stuff up, since they're pretty much useless without the ability to wait on them.

~Kyle

Dragoș Sbîrlea

unread,
Jan 3, 2014, 7:10:58 PM1/3/14
to qthr...@googlegroups.com
I just realized there may be another solution: I could use blocking OS
calls to temporarily block the threads, like waiting on a pthreads
semaphore or lock. However, when I tried it the wait calls on the
semaphores seem to behave like no-ops for some reason. Does qthreads
intercept these calls to prevent exactly what I am trying to
accomplish?
Best,
Dragos

Dragoș Sbîrlea

unread,
Jan 3, 2014, 9:54:14 PM1/3/14
to qthr...@googlegroups.com
Solved - it was Mac OS X which decided not to implement some of the
semaphore functions.

This approach works to temporarily disable the threads:
1. Create a semaphore with initial count 0.
2. Spawn tasks that perform a decrease followed by an increase in the
count, the number of tasks being NO_WORKERS-1.
3. Use the other parallel library
4. Do an increase in the count by 1 to restart the threads.

My current issue is that this approach is incompatible with the task
caching approach. If (with the caching enabled) I do a yield to flush the
cache, the main thread seems to hang and no thread takes over the rest
of the function.
Best,
Dragos
Reply all
Reply to author
Forward
0 new messages