The FlightGear Main Loop: Difference between revisions
m (cat) |
m (Switch to the {{forum url}} and {{forum link}} templates for all forum links.) |
||
Line 6: | Line 6: | ||
|1= 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. | |1= 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=273262}} | ||
| title = <nowiki>Re: FlightGear not using all computer power</nowiki> | | title = <nowiki>Re: FlightGear not using all computer power</nowiki> | ||
| author = <nowiki>sanhozay</nowiki> | | author = <nowiki>sanhozay</nowiki> | ||
Line 16: | Line 16: | ||
|1= 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. | |1= 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=270728}} | ||
| title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | | title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 30: | Line 30: | ||
In addition, there are special subsystems like the FDM, which are running FDM-coupled, i.e. interleaved, several times per timestep (typically 120 times) | In addition, there are special subsystems like the FDM, which are running FDM-coupled, i.e. interleaved, several times per timestep (typically 120 times) | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=271671}} | ||
| title = <nowiki>Re: interpolate() locks autopilot?</nowiki> | | title = <nowiki>Re: interpolate() locks autopilot?</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 47: | Line 47: | ||
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. | 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=184109}} | ||
| title = <nowiki>Re: Flightgear plotter updated.</nowiki> | | title = <nowiki>Re: Flightgear plotter updated.</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 58: | Line 58: | ||
|1= 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". | |1= 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". | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=205831}} | ||
| title = <nowiki>Re: Integration of Flight Illusion simgauges</nowiki> | | title = <nowiki>Re: Integration of Flight Illusion simgauges</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 72: | Line 72: | ||
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. | 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: | To learn more, see: {{forum link|p=153298}} | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=237652}} | ||
| title = <nowiki>Re: FG 64bit & Linux dependencies</nowiki> | | title = <nowiki>Re: FG 64bit & Linux dependencies</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 93: | Line 93: | ||
So you would be "safe" to do background processing using worker threads, e.g. for calculations - as long as you don't access any FG specific extension functions, which includes timers, listeners etc | So you would be "safe" to do background processing using worker threads, e.g. for calculations - as long as you don't access any FG specific extension functions, which includes timers, listeners etc | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=269360}} | ||
| title = <nowiki>Re: Space Shuttle</nowiki> | | title = <nowiki>Re: Space Shuttle</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 105: | Line 105: | ||
|1= restrictions due to FlightGear's architecture, i.e. its main loop, the proeprty tree and extension APIs not being thread-safe | |1= restrictions due to FlightGear's architecture, i.e. its main loop, the proeprty tree and extension APIs not being thread-safe | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=270576}} | ||
| title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | | title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 120: | Line 120: | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=153269}} | ||
| title = <nowiki>Re: [SUGGESTION] Multi-core FlightGear support</nowiki> | | title = <nowiki>Re: [SUGGESTION] Multi-core FlightGear support</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 135: | Line 135: | ||
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. | 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=153295}} | ||
| title = <nowiki>Re: [SUGGESTION] Multi-core FlightGear support</nowiki> | | title = <nowiki>Re: [SUGGESTION] Multi-core FlightGear support</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 154: | Line 154: | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=217790}} | ||
| title = <nowiki>Re: questions about performance with openscenegraph</nowiki> | | title = <nowiki>Re: questions about performance with openscenegraph</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 165: | Line 165: | ||
|1= 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. | |1= 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=217790}} | ||
| title = <nowiki>Re: questions about performance with openscenegraph</nowiki> | | title = <nowiki>Re: questions about performance with openscenegraph</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 192: | Line 192: | ||
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. | 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. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=202236}} | ||
| title = <nowiki>Re: extra500 - Avidyne Entegra 9 IFD - approach</nowiki> | | title = <nowiki>Re: extra500 - Avidyne Entegra 9 IFD - approach</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 214: | Line 214: | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=270656}} | ||
| title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | | title = <nowiki>Re: FGPython an propose for Python as an nasal alternative</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 232: | Line 232: | ||
the props.Node wrappers are slower than getprop/setprop because there's more Nasal-space overhead. Intuitively, the props.Node stuff should be faster, because of the cached reference - but the getprop()/setprop() code is native C code that uses a heavily optimied algorithm to look up properties (this may change once Tom ported the props bindings to use his cppbind framework). | the props.Node wrappers are slower than getprop/setprop because there's more Nasal-space overhead. Intuitively, the props.Node stuff should be faster, because of the cached reference - but the getprop()/setprop() code is native C code that uses a heavily optimied algorithm to look up properties (this may change once Tom ported the props bindings to use his cppbind framework). | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=183765}} | ||
| title = <nowiki>Re: Reading properties</nowiki> | | title = <nowiki>Re: Reading properties</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 243: | Line 243: | ||
|1= a listener would be quite appropriate for an on/off switch or similar, an update loop for everything that needs to be updated each frame/update (i.e. engine rpm), and if something is changing every frame anyways or is a tied property, you might as well use the update loop for several reasons: besides the fact that it might be necessary, it linearies your data flow and moves it closer to the use of the data, it makes use of the current known efficiency of getprop(), and I would venture that it seems most familiar to you. I really wouldn't worry about listener efficiency here, but then again what do I know (I have very little experience in real-time systems). | |1= a listener would be quite appropriate for an on/off switch or similar, an update loop for everything that needs to be updated each frame/update (i.e. engine rpm), and if something is changing every frame anyways or is a tied property, you might as well use the update loop for several reasons: besides the fact that it might be necessary, it linearies your data flow and moves it closer to the use of the data, it makes use of the current known efficiency of getprop(), and I would venture that it seems most familiar to you. I really wouldn't worry about listener efficiency here, but then again what do I know (I have very little experience in real-time systems). | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=183774}} | ||
| title = <nowiki>Re: Reading properties</nowiki> | | title = <nowiki>Re: Reading properties</nowiki> | ||
| author = <nowiki>Philosopher</nowiki> | | author = <nowiki>Philosopher</nowiki> | ||
Line 255: | Line 255: | ||
|1= t's NOT a "background process" at all - it will be triggered by the property tree once a node is accessed, which will invoke the Nasal callback. Timers and listeners are NOT background "processes". They are just invoked by different subsystems, i.e. the property tree (listeners) or the events subsystem (timers). There are other subsystems that can also invoke Nasal handlers, such as the GUI system or the AI code. This all takes place inside the FG main loop (=main thread), not some background/worker thread. Which is also the reason why all the Nasal APIs are safe to be used. | |1= t's NOT a "background process" at all - it will be triggered by the property tree once a node is accessed, which will invoke the Nasal callback. Timers and listeners are NOT background "processes". They are just invoked by different subsystems, i.e. the property tree (listeners) or the events subsystem (timers). There are other subsystems that can also invoke Nasal handlers, such as the GUI system or the AI code. This all takes place inside the FG main loop (=main thread), not some background/worker thread. Which is also the reason why all the Nasal APIs are safe to be used. | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=183772}} | ||
| title = <nowiki>Re: Reading properties</nowiki> | | title = <nowiki>Re: Reading properties</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 279: | Line 279: | ||
Started here: [[Using listeners and signals with Nasal#Behind the Scenes of Listeners]] | Started here: [[Using listeners and signals with Nasal#Behind the Scenes of Listeners]] | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=183776}} | ||
| title = <nowiki>Re: Reading properties</nowiki> | | title = <nowiki>Re: Reading properties</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> | ||
Line 297: | Line 297: | ||
|2= {{cite web | |2= {{cite web | ||
| url = | | url = {{forum url|p=183819}} | ||
| title = <nowiki>Re: Reading properties</nowiki> | | title = <nowiki>Re: Reading properties</nowiki> | ||
| author = <nowiki>Hooray</nowiki> | | author = <nowiki>Hooray</nowiki> |
Latest revision as of 11:23, 8 June 2019
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:
|