Runtime Arguments

30: Available compute: way more than you need, right up until you need it!


Listen Later

You almost never have exactly the right amount of compute for the job. Either cores are sitting idle while your code runs on one, or you've got more problem than machine. This episode is about the two fundamental tools for closing that gap — and why picking the wrong one makes things slower, not faster.

Topics covered:

  • Concurrency vs. parallelism — the core distinction: concurrency is a scheduling problem (you're waiting a lot); parallelism is a compute problem (you need more processing). They are not interchangeable.
  • IO-bound vs. CPU-bound — how to identify which problem you actually have before writing a line of concurrent code. (And a third case: memory-bound, where the fix is data layout, not more cores.)
  • Threads aren't always what you think — system-level vs. user-level threads; why JavaScript's `async`/`await` is single-threaded concurrency and not parallelism; why Go routines can be either.
  • Colored functions / async infection — why `async` spreads through a codebase the way `const` does in C++, and why Go sidesteps it entirely with `go func()`.
  • Go channels and Rust ownership — why these two language designs are the cleanest modern answers to shared-state problems.
  • Python's GIL — what it was, why it hurt, and why 3.14+ removes it (with caveats for single-threaded performance).
  • Amdahl's Law — the mathematical ceiling on how much any parallelization effort can help, and why it's specific to your problem.
  • Hidden parallelism — CPU pipelines and branch prediction run in parallel below your abstraction layer, and you can't see them without special tools.
  • Communication is the real enemy — GPU bus bandwidth, cluster fabric, Apple Silicon shared memory vs. NVIDIA CUDA: the cost of moving data often swallows the benefit of more cores.
  • Fork and copy-on-write — how Unix `fork` got fast, and why Python's reference counting undermines it.
  • The actor model — how Erlang (and now Swift) solve the ownership problem by letting the object own the data, not the caller.
  • Heisenbugs — the bugs that live in parallel code and only appear when you least want them.


Examples:

  • Pixar render farms — 130,000 frames × 24 hours each, solved by embarrassingly parallel independent frames
  • `make -j` — the classic CPU-bound parallelism win; why it only helps when you have real cores, not threads
  • Trolltech's distributed C++ build system — compile-farm tied to a specific commit, object files cached and shared
  • JavaScript worker threads and Web Workers — breaking out of the four-query Node.js limit


Link to Wolf's dap-mux presentation at mug.org: https://www.youtube.com/live/iyAk8-oE6cM?t=1725


Hosts:
Jim McQuillan can be reached at [email protected]
Wolf can be reached at [email protected]

Follow us on Mastodon: @[email protected]

If you have feedback for us, please send it to [email protected]

Checkout our webpage at http://RuntimeArguments.fm

Theme music:
Dawn by nuer self, from the album Digital Sky

...more
View all episodesView all episodes
Download on the App Store

Runtime ArgumentsBy Jim McQuillan & Wolf