The FlightGear Main Loop
This article is a stub. You can help the wiki by expanding it. |
Background
The bulk of the work that Flightgear does to simulate flight on your screen happens in a single thread on a single core of your processor. Some multithreading is possible but you tend to get one core running at 100% with other cores hardly doing anything by comparison. — sanhozay (Jan 18th, 2016). Re: FlightGear not using all computer power.
(powered by Instant-Cquotes) |
your whole notion of "processes" is already where you are mistaken, FG's main loop is really just a huge ugly nested for-loop that calls the ->update(double dt) loop of each SGSubsystem/Mgr instance (think fdm, audio, nasal etc) - but there are still a handful of pseudo-subsystems that don't even use this design, while others are working behind the scenes in background threads (mainly in simgear), or are interleaved with the FDM. — Hooray (Dec 30th, 2015). Re: FGPython an propose for Python as an nasal alternative.
(powered by Instant-Cquotes) |
Multi-threading
While the main loop is indeed single-threaded, there are a bunch of systems that do make use of additional cores, see: Howto:Activate multi core and multi GPU support
You can also run certain Nasal computations asynchronously using Nasal's "thread.newthread()" API: http://plausible.org/nasal/lib.html However, care must be taken not to call ANY of the standard extension functions - i.e. ALL the FG APIs, including property tree access through getprop/setprop, props.nas etc. The canvas itself is single-threaded currently, but we once talked about using OSG's multithreading support to update textures independently, and not just sequentially, while groups and nested canvases would still need to be updated in a serialied fashion, other groups and canvases could be updated in parallel. |
I think the misconception is that he thinks our main loop is multi-threaded, while it is indeed entirely sequential. Like Philosopher said, each subsystem in FlightGear gets called to run its update() method, including the FDM, autopilot, scenery, terrain, sound, scripting, I/O etc - there's a fixed pre-determined order. Each stage gets to see the state as it was left over from the previous stage. It would require a fair bit of sophistication and internals knowledge to mess this up (and I can only really come up with two methods, without going into specifics). And like Philosopher says, you can explicitly design for this by using a "signal" property that signals "completeness". — Hooray (Apr 13th, 2014). Re: Integration of Flight Illusion simgauges.
(powered by Instant-Cquotes) |
the fgfs main loop itself is single-threaded primarily. While Nasal does provide support for threading, the majority of the FG-level interface is not thread-safe at all, including most extension functions and other subsystems. The majority of subsystems (i.e. those not using SGThread) are also single-threaded, which includes recent additions like Canvas.
The FDM itself is also a singleton by design while also being strictly single-threaded, with the fixed assumption that there's only ever a single FDM being used. Subsystems are structured in a "cooperative multi-tasking (time sliced)" fashion, meaning that one subsystem lagging behind would slown down all the others accordingly - e.g. the Nasal garbage collector is being run in the main thread, which makes frame rate/spacing non-deterministic for the other subsystems that are not FDM-interleaved. To learn more, see: [1] |
restrictions due to FlightGear's architecture, i.e. its main loop, the proeprty tree and extension APIs not being thread-safe — Hooray (Dec 29th, 2015). Re: FGPython an propose for Python as an nasal alternative.
(powered by Instant-Cquotes) |
OSG Threading
SG threading support is largely specific to offloading rendering-related computations to different threads, it will NOT directly help conventional FlightGear subsystems runing in the main loop, not without explicit coding - i.e. multi-threading or multi-processing and IPC. — Hooray (Mar 15th, 2012). Re: [SUGGESTION] Multi-core FlightGear support.
(powered by Instant-Cquotes) |
OSG threading is neat and dandy, but obviously it is only directly useful for rendering related paralleliation and related work. On the other hand, none of this comes for free. OSG's threading support really is impressive, but all those OSG threads must be kept busy. Properly. That's exactly the work that FlightGear is responsible for in its main loop.
OSG's multithreading support doesn't just come "automagically", just because FlightGear uses OSG. The multithreading support in OSG must be explicitly supported by following certain OSG coding patterns and coding protocols. Otherwise, you won't benefit at all. Obviously, OSG really is extremely powerful and also pretty good at parallelizing things, but you cannot necessarily see that when running FlightGear, but there is other OSG-based software which is making really good use of this.— Hooray (Mar 15th, 2012). Re: [SUGGESTION] Multi-core FlightGear support.
(powered by Instant-Cquotes) |
FlightGear itself doesn't make very much use of OSG's support for threading (background jobs), and like you've found out, certain flags need to be set to tell OSG to "try" to do things in parallel. But overall, OpenGL rendering (and thus OSG rendering) is perdominantly single-threaded. The only thing that can be done by applications like FlightGear is to use OSG infrastructure (coding patterns) that can internally be parallelied by OSG.
These OSG "coding patterns" are typically based on standard design patterns that are mapped onto OpenThreads to parallelize rendering related tasks. Basically, as long as the proper coding patterns are used, OSG is smart enough to split up the workload for each frame and use different threads whenever possible and keep the GPU saturated. Whenever that is not possible, everything will be done in the main thread, which means that latencies will become worse and framerate lower.— Hooray (Sep 4th, 2014). Re: questions about performance with openscenegraph.
(powered by Instant-Cquotes) |
Much of the code comprising the FlightGear rendering pipeline was ported from PLIB/SG and hasn't been updated in years - thus, isn't yet necessarily using the right/best OSG coding patterns or protocols - which is why applications like fgviewer (or osgviewer) will typically perform better than fgfs. In addition, there's a ton of code running in the FG main loop that is adding to mainloop slowness despite not belonging into the rendering/main thread, which is why a few core developers have been working towards moving non-rendering related code out of the main loop into worker threads, and eventually also into HLA federates. "fgviewer" is all about coming up with a lightweight viewer component that doesn't run any non-rendering related subsystems at all. — Hooray (Sep 4th, 2014). Re: questions about performance with openscenegraph.
(powered by Instant-Cquotes) |
I don't think we're currently really using any multi-threaded OSG rendering. Our property tree code isn't really thread safe, and neither are the corresponding extension functions.
It may be worthwhile to explore threading at some point, especially for canvases that don't have any external dependencies (i.e. no referenced canvas that would require serialiing). For OSG it would then be friendlier to use a real scenegraph for each group/element, so that optimizations become possible. Technically, we would need to use one dedicated SGPropertyNode for each canvas and use serialization at the property tree level. That would then allow us to run all updates asynchronously, and only serialize getprop() accesses to the main property tree. For example, each canvas would have its own property tree (SGPropertyNode_ptr), and we could have a single dedicated update thread that runs all updates. For all "self-contained" canvases, that would mean that they could be updated in parallel - without stuff having to run in the main loop. But for this to be worthwhile, we would need to adopt more OSG:: data structures to map Canvas elements/groups, e.g. onto osg::switch etc This would require a bit of Nasal-level restructuring, to ensure that we use different APIs for accessing the canvas property tree (thread) and the main tree. But overall this should be pretty doable thanks to the property tree-centric nature of canvas. We would just need to make sure that each canvas has its own tree. If anybody is interested in exploring this, let me know, I can probably help a bit with this and come up with a basic prototype that is only serialized with the main loop to ensure that changes take effect.— Hooray (Mar 1st, 2014). Re: extra500 - Avidyne Entegra 9 IFD - approach.
(powered by Instant-Cquotes) |
Initialization
Adding a new subsystem
conventional subsystem:
|
Update
Reset/Re-init
Nasal
Listeners
that's a misconception related to listeners: listeners are not actively "listening" at all - there's no "listener watch" running - instead, it works basically like this:
|