You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Higher Order Co's Bend/HVM (https://higherorderco.com) gets automatic parallelism by running everything on an interaction-combinator graph reducer. We deliberately do NOT adopt that engine, it is a VM with GC-adjacent semantics, the exact runtime our no-VM / no-GC / compile-to-native identity rejects (same conclusion recorded for Fil-C's FUGC and Objective-S's metaobject protocol).
What DOES port is the ergonomic idea, not the runtime: parallelism expressed as structure, not thread code ("write divide-and-conquer, get multi-core for free"). We can likely deliver the realistic 80% of that as a thin library over machinery we already shipped, but it must earn its place on measured numbers, not vibes. This issue is to spike + benchmark + test, then make a go/no-go call. No stdlib commitment until the data justifies it.
What already exists (so this is a library layer, not a new runtime)
std.worker bounded thread pool: run submits to it; pool_size / aether_worker_pool_configure / pool_shutdown. Off-scheduler, so it does not starve actor cores.
Isolated[T] (Language: Isolated[T] wrapper for actor message types (Nim-inspired) #479): move-only, compile-time-checked, zero runtime cost. This is the linearity that makes fork-join race-free by construction (share nothing, move ownership across the split), the same discipline that lets interaction nets run lock-free.
docs/structured-concurrency.md for the conceptual home.
Missing: any parallel_map / parallel fold combinator.
Spike (branch only, not merged until numbers land)
Prototype worker.parallel_map(list, f) and a parallel fold/reduce that dispatches independent branches onto the existing bounded pool.
Payloads carried as Isolated[T] so subtasks cannot share mutable state; misuse is a compile error via the existing move checker.
Auto-fallback to sequential below a measured threshold N (see benchmark 2).
Benchmarks to run (the actual deliverable)
Speedup vs core count. CPU-bound divide-and-conquer (e.g. parallel mergesort, mandelbrot tiles, or an n-body step). Wall-time at pool_size 1/2/4/8/ncores. Target: near-linear up to core count.
Overhead floor / crossover. Same op sequential vs parallel at small N. Find the N where parallel first wins; that threshold becomes the auto-sequential fallback point. If the crossover is huge, the layer is not worth it.
vs hand-rolled actors. Compare against the same fan-out done with spawn + ?/reply. The combinator must not be slower than rolling it by hand, or it is just sugar with a tax.
Safety under sanitizers. ASan/UBSan/LSan clean, pool joins cleanly, no leaks across thousands of iterations; confirm the Isolated move-checker rejects a shared-capture attempt at compile time.
Decision criteria (go / no-go)
Ship ONLY if: near-linear speedup on CPU-bound work, a small-enough crossover N to be broadly useful, zero leaks/races, and the call site reads declaratively (structure, not thread handles). Otherwise document the finding and close.
Explicit non-goals (do not port, they need the runtime we reject): the interaction-combinator engine, optimal reduction, the GPU/CUDA backend. If a real workload ever needs true HVM-grade parallelism, the Aether-shaped move is to HOST HVM as a guest (contrib.host.*), not reimplement it, and only after a license check.
Artifacts
Benchmark harness under benchmarks/ (or tests/).
A short findings note in the docs/cross-references/ style (bend.md), recording the numbers and the go/no-go.
If go: a follow-up implementation issue with the measured threshold baked into the API.
Motivation
Higher Order Co's Bend/HVM (https://higherorderco.com) gets automatic parallelism by running everything on an interaction-combinator graph reducer. We deliberately do NOT adopt that engine, it is a VM with GC-adjacent semantics, the exact runtime our no-VM / no-GC / compile-to-native identity rejects (same conclusion recorded for Fil-C's FUGC and Objective-S's metaobject protocol).
What DOES port is the ergonomic idea, not the runtime: parallelism expressed as structure, not thread code ("write divide-and-conquer, get multi-core for free"). We can likely deliver the realistic 80% of that as a thin library over machinery we already shipped, but it must earn its place on measured numbers, not vibes. This issue is to spike + benchmark + test, then make a go/no-go call. No stdlib commitment until the data justifies it.
What already exists (so this is a library layer, not a new runtime)
std.workerbounded thread pool:runsubmits to it;pool_size/aether_worker_pool_configure/pool_shutdown. Off-scheduler, so it does not starve actor cores.Isolated[T](Language: Isolated[T] wrapper for actor message types (Nim-inspired) #479): move-only, compile-time-checked, zero runtime cost. This is the linearity that makes fork-join race-free by construction (share nothing, move ownership across the split), the same discipline that lets interaction nets run lock-free.docs/structured-concurrency.mdfor the conceptual home.Missing: any
parallel_map/ parallel fold combinator.Spike (branch only, not merged until numbers land)
worker.parallel_map(list, f)and a parallel fold/reduce that dispatches independent branches onto the existing bounded pool.Isolated[T]so subtasks cannot share mutable state; misuse is a compile error via the existing move checker.Benchmarks to run (the actual deliverable)
spawn+?/reply. The combinator must not be slower than rolling it by hand, or it is just sugar with a tax.Decision criteria (go / no-go)
Ship ONLY if: near-linear speedup on CPU-bound work, a small-enough crossover N to be broadly useful, zero leaks/races, and the call site reads declaratively (structure, not thread handles). Otherwise document the finding and close.
Explicit non-goals (do not port, they need the runtime we reject): the interaction-combinator engine, optimal reduction, the GPU/CUDA backend. If a real workload ever needs true HVM-grade parallelism, the Aether-shaped move is to HOST HVM as a guest (
contrib.host.*), not reimplement it, and only after a license check.Artifacts
benchmarks/(ortests/).docs/cross-references/style (bend.md), recording the numbers and the go/no-go.