Why is this? It's something I've heard a lot but I don't understand why. Is it something fundamental about audio, or is it simply the case that The Application With the Mindshare isn't architectured in a way that multithreading works well?
Personally, my day job is working on a program that could support 4-16-64 threads just fine, but since a lot of the core architecture is from the 90s and there's a giant ball of globals, component object model/single threaded apartment spaghetti deep under the hood, multithreading even trivially parallelizable tasks is fraught with peril. Fortunately for my employer, we are an entrenched 800 pound gorilla, and we can skate on momentum while these issues get fixed. So I totally understand if it's the same in a specialized space like DAW.
re: Skyrim. That engine is a fork of a fork of an engine that was written in 1997. Skyrim ran like garbage when it was released in 2011. It has nothing to do with open world or so forth, it's just run of the mill legacy architecture problems. ARMA3 (released 2013) is in a similar boat- it's a very old game engine written by a very small (they're not indie, but they're close) development studio. Both of these studios have the same problem my employer has- they have a bunch of legacy cruft that's difficult to migrate away from.
There's a tipping point somewhere. With two physical cores, you don't gain that much from farming stuff out to the different cores. A lot of multithreaded stuff from that era had a sequential-concurrent model. Your one large task was broken down in a sequential series of subtasks. (usually it was gather input, do AI, do physics, do drawing) Sometimes those subtasks would break out into N threads, which do a small amount of stuff in parallel, then there's a "join the world" event, you move on to the next subtask. Think links of sausages; sometimes it's wide, sometimes it's narrow, but you never have two sausages at the same time. This model is very sensitive to single threaded performance, because all of the join the world events are single threaded, and at the end there's a giant pile of single threaded calls to OpenGL which is a single threaded API.
We're steadily moving away from that. First of all, the game loop went from having a giant mutable ball of state, to having a generational immutable world state. One pile of threads would compute world state generation N+1, and a second giant pile of threads would draw world state generation N. Both would depend on generation N, but since generation N was immutable, that was fine. This can be broken down further- it's fine to generate new AI priorities for gen N+1 using the physics state from gen N, and use the AI priorities defined in gen N to do physics to generate gen N+1. So AI and physics can happen on independent threads. This can be broken down further- chop the world up into zones, and give responsibility for each zone to individual jobs. We're also switching from OpenGL (with its internal state machine, single threaded API) to Vulkan, which has completely blown open the drawing steps. I think Valve did some benchmarking where where the single threaded chunk of OpenGL took 5ms, (which is an eternity) but the single threaded chunk of Vulkan was ~1 microsecond. The 4.999ms of CPU time still exists under Vulkan, it didn't just go away- but now it can happen in parallel on multiple threads. Instead of having 3-20 join the world events each frame, there's only one, and the only thing that happens there is a pointer swap.
The industry is moving away from single threaded engines like ARMA3's and Bethesda's in house engines. For the most part, AAA games since ~5 years ago properly utilize multiple cores. ARMA3 and Skyrim are dinosaurs, and they've aged about as well.
Why is this? It's something I've heard a lot but I don't understand why. Is it something fundamental about audio, or is it simply the case that The Application With the Mindshare isn't architectured in a way that multithreading works well?
Personally, my day job is working on a program that could support 4-16-64 threads just fine, but since a lot of the core architecture is from the 90s and there's a giant ball of globals, component object model/single threaded apartment spaghetti deep under the hood, multithreading even trivially parallelizable tasks is fraught with peril. Fortunately for my employer, we are an entrenched 800 pound gorilla, and we can skate on momentum while these issues get fixed. So I totally understand if it's the same in a specialized space like DAW.
re: Skyrim. That engine is a fork of a fork of an engine that was written in 1997. Skyrim ran like garbage when it was released in 2011. It has nothing to do with open world or so forth, it's just run of the mill legacy architecture problems. ARMA3 (released 2013) is in a similar boat- it's a very old game engine written by a very small (they're not indie, but they're close) development studio. Both of these studios have the same problem my employer has- they have a bunch of legacy cruft that's difficult to migrate away from.
There's a tipping point somewhere. With two physical cores, you don't gain that much from farming stuff out to the different cores. A lot of multithreaded stuff from that era had a sequential-concurrent model. Your one large task was broken down in a sequential series of subtasks. (usually it was gather input, do AI, do physics, do drawing) Sometimes those subtasks would break out into N threads, which do a small amount of stuff in parallel, then there's a "join the world" event, you move on to the next subtask. Think links of sausages; sometimes it's wide, sometimes it's narrow, but you never have two sausages at the same time. This model is very sensitive to single threaded performance, because all of the join the world events are single threaded, and at the end there's a giant pile of single threaded calls to OpenGL which is a single threaded API.
We're steadily moving away from that. First of all, the game loop went from having a giant mutable ball of state, to having a generational immutable world state. One pile of threads would compute world state generation N+1, and a second giant pile of threads would draw world state generation N. Both would depend on generation N, but since generation N was immutable, that was fine. This can be broken down further- it's fine to generate new AI priorities for gen N+1 using the physics state from gen N, and use the AI priorities defined in gen N to do physics to generate gen N+1. So AI and physics can happen on independent threads. This can be broken down further- chop the world up into zones, and give responsibility for each zone to individual jobs. We're also switching from OpenGL (with its internal state machine, single threaded API) to Vulkan, which has completely blown open the drawing steps. I think Valve did some benchmarking where where the single threaded chunk of OpenGL took 5ms, (which is an eternity) but the single threaded chunk of Vulkan was ~1 microsecond. The 4.999ms of CPU time still exists under Vulkan, it didn't just go away- but now it can happen in parallel on multiple threads. Instead of having 3-20 join the world events each frame, there's only one, and the only thing that happens there is a pointer swap.
The industry is moving away from single threaded engines like ARMA3's and Bethesda's in house engines. For the most part, AAA games since ~5 years ago properly utilize multiple cores. ARMA3 and Skyrim are dinosaurs, and they've aged about as well.