views:

97

answers:

5

I have a program with a main thread and a diagnostics thread. The main thread is basically a while(1) loop that performs various tasks. One of these tasks is to provide a diagnostics engine with information about the system and then check back later (i.e. in the next loop) to see if there are any problems that should be dealt with. An iteration of the main loop should take no longer than 0.1 seconds. If all is well, then the diagnostic engine takes almost no time to come back with an answer. However, if there is a problem, the diagnostic engine can take seconds to isolate the problem. For this reason each time the diagnostic engine receives new information it spins up a new diagnostics thread.

The problem we're having is that the diagnostics thread is stealing time away from the main thread. Effectively, even though we have two threads, the main thread is not able to run as often as I would like because the diagnostic thread is still spinning.

Using Boost threads, is it possible to limit the amount of time that a thread can run before moving on to another thread? Also of importance here is that the diagnostic algorithm we are using is blackbox, so we can't put any threading code inside of it. Thanks!

A: 

From the way you've worded your question, it appears that you're not quite sure how threads work. I assume by "the amount of time that a thread can run before moving on to another thread" you mean the number of cpu cycles spent per thread. This happens hundreds of thousands of times per second.

Boost.Thread does not have support for thread priorities, although your OS-specific thread API will. However, your problem seems to indicate the necessity for a fundamental redesign -- or at least heavy profiling to find bottlenecks.

rlbond
Since I *am* pretty new to thread programming, there certainly is a possibility that I misunderstand things. However the example you cited is more likely a poor choice in words. If I have thread A and thread B, then I would expect the OS to switch back and forth between A and B pretty quickly so that to a user of a GUI in thread A it appears that A is always on. In my case it seems that the OS is allowing thread B to run for 2 seconds before switching back to thread A. Why would this be? (Also, tell me if I'm still confused on some threading issue.)
John Berryman
Threads will not block like this. Your OS should not be allowing this. However, it should be possible to use your profiler to determine the actual time spent in each thread.
rlbond
I've never used a profiler. Any recommendations? My IDE is Eclipse CDT and I'm using the gnu tool chain (gcc, g++, make, gdb).
John Berryman
A: 

You can't do this generally at the OS level, so I doubt boost has anything specific for limiting execution time. You can kinda fake it with small-block operations and waits, but it's not clean.

I would suggest looking into processor affinity, either at a thread or process level (this will be OS-specific). If you can isolate your diagnostic processing to a limited subset of [logical] processors on a multi-core machine, it will give you a very course mechanism to control maximum execution amount relative to the main process. That's the best solution I have found when trying to do a similar type of thing.

Hope that helps.

Nick
+1  A: 

looks like your threads are interlocked, so your main thread waits until background thread finished its work. check any multithreading sychronization that can cause this.

to check that it's nothing related to OS scheduling run you program on double-core system, so both threads can be executed really in parallel

Andrew Tylychko
That's just what I was thinking, but during the main loop I query the diagnostic loop to see if it's already busy. When it is busy, I print this message to the screen. In the case where my program appears to be hanging, I well see at least one, but sometimes several "Diagnostics thread is busy" messages. Perhaps it's still something else, but I think that if the check comes back as *busy* then I don't do anything else that would interfere with that thread.
John Berryman
+1  A: 

If you run multiple threads they will indeed consume CPU time. If you only have a single processor, and one thread is doing processor intensive work then that thread will slow down the work done on other threads. If you use OS-specific facilities to change the thread priority then you can make the diagnostic thread have a lower priority than the main thread. Also, you mention that the diagnostic thread is "spinning". Do you mean it literally has the equivalent of a spin-wait like this:

while(!check_done()) ; // loop until done

If so, I would strongly suggest that you try and avoid such a busy-wait, as it will consume CPU time without achieving anything.

However, though multiple threads can cause each other to slow-down, if you are seeing an actual delay of several seconds this would suggest there is another problem, and that the main thread is actually waiting for the diagnostic thread to complete. Check that the call to join() for the diagnostic thread is outside the main loop.

Another possibility is that the diagnostic thread is locking a mutex needed by the main thread loop. Check which mutexes are locked and where.

To really help, I'd need to see some code.

Anthony Williams
A: 

I recommend intel's thread building blocks. tbb::task is what you need. you can synchronize the tasks without using mutexes, locks, contiditonal variables and creating tasks are much more light-weighted than creating or destroying threads.
I have written a part of my algorithmic trading platform with using tbb. calling 1 million indicator functions per second and still < 1 % cpu usage with intel i5 750 with 4 cores.

bahadir