PDA

View Full Version : Can the GUI be run from within a QThread rather than the "main" thread?



Eos Pengwern
22nd October 2010, 00:16
I have a classic calculation-intensive GUI application where calculations needed to keep the GUI up-to-date are performed in a separate QThread, passing the results back to the GUI for display when ready via the signals-and-slots mechanism. The 'run' function within the QThread passes most of the calculations on to a separate DLL, written in Fortran, which does the actual number-crunching. The Fortran DLL routines, in turn, are parallelised using OpenMP.

If I compile my Fortran code with the Intel compiler, this works fine. However, I have been evaluating another Fortran compiler which, when it works, runs about three times as fast. However, it often crashes when entering an OpenMP section, and the compiler vendor tells me that it's because it's unhappy trying to set up the OpenMP thread team from within what is already a sub-thread of the main application. They suggest having the "main" thread doing the calculations while a sub-thread operates the GUI.

Is this possible using Qt? I guess that the thread used for the GUI is determined in the "main" routine:



QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();

...and its not obvious to me how I would either farm "w.show" out to a different thread or assign any other QObject to the main event loop.

Is there, in fact, a way of doing this?

Thanks,
Stephen.

tbscope
22nd October 2010, 05:35
Why not put your calculation code in a separate process? Then your process has its own main thread and your gui program has its main thread. You then use iterprocess communication to update the gui.

Eos Pengwern
22nd October 2010, 10:25
I suppose that I could put the calculation in a separate process and use TCP/IP for the inter-process communication without overly major restructuring of the code, but I suspect that the overhead involved would negate the advantage of using OpenMP for all but the longest calculations. D-Bus or QCOP may be more efficient but I can't afford to be tied only to Linux at this point.

wysota
22nd October 2010, 10:32
You can use shared memory as the communication medium.

Eos Pengwern
22nd October 2010, 10:50
I think that would be more difficult to implement, simply because unlike TCP/IP or signals-and-slots it's not event-based; that is to say, each application would need to poll the memory for changes. No doubt it could be done, but perhaps not so easily.

I'm coming round to the view that the simplest way ahead might be to move the calculation itself back into the main thread, and to have the Fortran code call a "GUI update" function at intervals, for example each time it emerges from a large parallelised loop. I have managed to do something very similar to this in the past by passing a pointer to a Qt callback function as one of the arguments when the Fortran code is invoked.

wysota
22nd October 2010, 11:04
Use QLocalSocket then. It'll bit a bit faster than a local tcp socket and provides an event-based processing. Using QCop or DBus would be slower anyway.

Eos Pengwern
22nd October 2010, 11:32
Hey, that looks neat...

mortoray
22nd October 2010, 12:17
I think that would be more difficult to implement, simply because unlike TCP/IP or signals-and-slots it's not event-based; that is to say, each application would need to poll the memory for changes. No doubt it could be done, but perhaps not so easily.

Linux and Windows (I believe) both support cross-process communciations using things like mutexes and events. You place your sensitive data in the shared memory, using a shared mutex, and then use a condition variable/event/pulse to trigger the other process. Failing that, they both support named pipes -- which appears to be what QLocalSocket is using.

Though in my opinion the vendor's reasoning is flawed. There is a very good chance that if you make the change you'll have the same problems. Parent/child threads aren't really handled differently by the OS's, not at least in such a way that it'd cause threaded code to crash.