RL Post-Training on Macs
Erfan Miahi
July 2026
We just finished a multi-turn reinforcement learning (RL) run of LFM2.5-8B-A1B, [2] an 8.3B-parameter MoE, on 14 Macs spread across four countries. And one of them was my MacBook. The Macs generated the rollouts; a single B200, an ocean away, did the training. On PaperSearchQA,[14] an agentic task where the model answers biomedical questions by searching a corpus of research papers, held-out pass@1 more than doubled, from 29% to 63%. As far as we can tell, this is the first time anything like this has happened: the largest multi-Mac setups we could find, eight EXO machines[9] and four RDMA-linked Mac Studios,[8] all had to be wired to each other. Here there are no wires.
Macs are one of the best hardware choices for post-training. Why? Because most of the compute in post-training is inference, and that's what Macs are good at. In reasoning and agentic RL, generating the rollouts takes most of the run's time, often above 90%.[6][5] We put the gradient step on a datacenter GPU. The rollouts don't need one; they need memory, enough for the model plus the KV cache of dozens of concurrent episodes. Unified memory holds both at sizes no consumer GPU can, and studies comparing Apple silicon against consumer NVIDIA cards keep finding it one of the most cost-effective ways to run large models.[21][22] MoEs suit it especially well: big in memory, light in compute.
However, this is not an easy system to build. Two problems stand in the way. First, the public internet: with no wires, every worker reaches the trainer over an ordinary internet connection. Those connections are drastically slow compared to a local interconnect, and the machines behind them come and go mid-run. Second, the off-policy gap. Every RL post-training system has one: the inference engine and the trainer never match exactly,[7][10] but the mismatch is usually mild. Ours is drastic: different hardware (Apple silicon vs an NVIDIA B200), a different kernel stack (MLX vs Megatron), a different precision (int8 vs bf16), and weights a few versions stale on top. The standard RL systems don't work in this setting.
In our setup:
- To the best of our knowledge, this is the first RL post-training run that used only consumer Macs for rollouts. We use fourteen mixed-generation Macs across four countries, connected over ordinary internet.
- The trainer trains while the Macs generate asynchronously. Nothing goes idle.
- Rollouts run in int8 on Apple's MLX;[3] the trainer runs bf16 on NVIDIA's Megatron.[4]
- Workers join, leave, or crash mid-run without stalling the run.
- Nothing caps the fleet size; we ran 14 Macs only because that saturated one B200.
- Each weight update ships about 110x smaller than a full checkpoint.
- Rollouts stream to the trainer as they finish, not at sweep end.
- Custom Metal paged-attention kernels, specialized for the LFM2.5 architecture.
- DPPO's token gate keeps training stable across a drastic off-policy gap.
- Held-out pass@1 more than doubles, from 29% to 63%.
- The full stack is open source.
The rest of this post explains how we made each piece work.
1 · What's the right topology for a fleet you can't wire?#
We begin with the topology. The communication pattern of the system is minimal: each Mac needs the newest weights, the trainer needs the generated rollouts, and no worker ever needs data from another worker. The fleet adds its own constraints: consumer Macs sit behind NAT, so no node can be required to accept an inbound connection; machines join and leave during a run; home connections vary wildly in speed and stall without warning, so nothing can run in lockstep. On the training side we assume the trainer runs within a centralized cluster, which makes that cluster the one source of truth for the weights. By this point the traffic is clearly shaped like a star (weights fan out one-to-many, rollouts gather many-to-one, and no edge connects two workers), so we chose a star as our topology; Figure 1 shows this topology.
Latency forced a second decision. The trainer and the Macs are disaggregated, an ocean and a consumer uplink apart, so every transfer between them carries real delay no matter how much we compress. A synchronous loop would spend most of its time waiting on that delay. So we made the decision to make the system fully asynchronous: the trainer stores arriving rollouts in a replay buffer and trains from it, each Mac generates from whatever weights it has, and nobody ever waits for anybody. Most of the design decisions in this post follow from that choice, and its price, the off-policy gap, gets a section of its own.
The hub is a storage bucket: plain S3-style object storage. The trainer writes each new version of the weights to the bucket and every Mac reads it back; generated rollouts flow the other way, one object per group. That's what the animation at the top of the post is showing: gold packets are rollouts converging on the trainer, navy packets are weight updates spreading back out to the Macs.
No machine ever has to accept an inbound connection, because everything is an outbound HTTPS request against storage.
Objects are only ever added, never edited in place, so a retried upload lands whole or not at all, and a single small pointer file names the newest version of the weights: a Mac joining mid-run reads the pointer, downloads the latest weights, and starts generating.
For storage we chose Cloudflare R2: the access pattern is write once, read by everyone, so egress dominates the bill (about 230 GB of weight pulls over this run alone, growing with every worker), and R2 charges nothing for egress.[18]
Still, the topology only decides where the bytes go, not how fast they get there. The star has to move ~9 GB of weights (the 8.3B-parameter model in int8, quantization scales included) out to every Mac every several minutes, and a constant stream of rollouts back. Sent the naive way, both arrive stale, and stale is exactly what destabilizes training. The next two sections discuss how we make this connection fast.
2 · Weight sync: home internet at datacenter speed#
We start with the weights, the largest payload the system moves. The trainer publishes a new version of the model roughly every ten minutes, and the int8 weights are 9 GB: at the global median speed, roughly 100 Mbps,[25] that download takes about ten minutes, the entire gap between versions. While it runs, the system has two options, and both are expensive. Either the trainer waits for rollouts generated on the new version, which leaves the one datacenter GPU in the system idle, or it keeps training on rollouts from weights that are now several versions old, which widens the off-policy gap that can destabilize a run. We wanted weight-sync to be so efficient that we never have to make either sacrifice.
To make this happen we use PULSE, a weight-sync technique that cuts what has to be sent by roughly a hundredfold.[13] It starts from a precision mismatch. The trainer keeps its master weights in fp32, and every optimizer step moves them by a tiny amount, on the order of the learning rate. The Macs never see that precision: rollout inference runs in int8, where a weight can only take one of 256 evenly spaced values per quantization group. Those few representable values form a coarse grid (Figure 2), and a weight's int8 value moves only when its accumulated fp32 movement crosses over to the next point on the grid. At RL learning rates (e.g., 10−6) almost no single update is that large, so the grid absorbs nearly all of them, and the int8 view of most weights is identical from one version to the next.
The trainer therefore ships only the weights whose int8 value changed, and the Mac reconstructs, bit for bit, the same int8 weights a full download would have given it. The PULSE paper works the mechanism out in detail: about 99% of per-step updates are invisible even at bf16, and the coarser the inference precision, the more the grid absorbs, so the cast that saves the Mac memory also buys the compression.[13]
Lower precision buys more compression, not less: our coarse int8 grid hides even more of each update than the bf16 the PULSE paper measured.
At a hundredfold, the 9 GB download becomes about 90 MB, and 90 MB over that median connection lands in about seven seconds, the same wall-clock as pulling the full 9 GB over a 10 Gbps link. For the heaviest traffic in the system, a home connection behaves similar to a datacenter connection. And our live run confirms it: a new version reached the bucket in seconds, not minutes.
Two more design decisions round out the sync, both taken from the PULSE paper, along with its recommendations for encoding the patches.[13] First, every delta is computed against the previous version, not against the last full snapshot. Diff against a fixed snapshot and the weight delta can only grow: weights keep crossing grid steps as training moves, so a few dozen versions out, each delta would carry a large fraction of the model. Diff against the previous version and each delta carries only the weights that crossed in that one publish interval, so deltas stay the same size no matter how long the run gets.
The cost is that a fresh Mac would have to replay every delta since the start, and that's the second decision: the trainer also publishes a full int8 anchor every twentieth version, purely as a starting point (Figure 3). A Mac that joins mid-run, or falls behind, downloads the newest anchor and replays the few deltas since the anchor, not the whole chain. And the anchor is int8 rather than bf16 on purpose: the download drops from 16.9 GB to 9 GB, and the weights sit at about 8.4 GB in memory, which is what makes a 16 GB personal MacBook viable as a worker.
3 · Rollout streaming: no group waits for the sweep#
Weights are half the traffic. The other half flows the opposite way: generated rollouts. Each Mac works in sweeps: one sweep is all eight of its groups (eight on an M4 Pro; a smaller Mac runs fewer), eight rollouts each, decoded together as one batched pass, with episodes evicted as they finish so they stop consuming compute.1
Shipping is decoupled from decoding in two places. First, uploads run on a background thread, so the decode loop never blocks on the network; we measured no decode-speed loss. Second, a group ships the moment its last episode finishes rather than when the whole sweep ends. As Figure 4 shows, the trainer starts consuming a Mac's first groups while that Mac is still decoding its last, and a slow episode delays only its own group. Rollouts arrive at the bucket as a steady stream rather than periodic bursts.
Figure 4 lays the whole system on one timeline, the ten minutes between one weight publish and the next: the Mac pulls a delta and runs its sweep, the groups land in the bucket as they finish, and the trainer fits four optimizer steps and publishes again. Nothing blocks anything else. Next section discusses how wide the sweep should be.
4 · Optimizing the inference engine: batch throughput vs per-rollout speed#
The last two sections made both transfers fast. What's left is the Macs themselves. When a Mac generates rollouts, two numbers matter: how many rollouts it completes per hour, and how long any single rollout takes. The second one matters more than it looks. A slow rollout arrives late, and a late rollout is more off-policy by the time the trainer sees it. So we made two decisions. First we optimized the inference stack itself, cutting wasted work so both numbers improve at once. Then we picked the batch size, how many sequences each Mac decodes at once. Raising it lifts rollouts per hour but slows every individual rollout, and we deliberately ran every Mac below its top batch throughput (aggregate tokens per second). That second decision sounds wrong until you see what a big batch does to staleness.
Both decisions were made empirically. All benchmarks in this section use the same setup: the production rollout path end to end on the reference M4 Pro, on the environment the run trains on (PaperSearchQA,[14] introduced in the results section), with a live retriever, the fleet's int8 quantization, and the run's sampling parameters. The questions are drawn at random from the run's question pool, the same pool its training mix was curated from. The exact set is at dataset link.
Every comparison runs three times, on three disjoint question sets. Each set is a fresh draw from that pool, and both configurations run each set with identical questions and random seeds, so every measurement comes in matched pairs. The pairing removes the two biggest sources of variance, question difficulty and sampling luck, so a paired difference isolates the effect of the cache. The three disjoint sets are independent replicates; they give each comparison a standard error, and we claim only differences that clear it. The clearest case, episodes per hour at 128 sequences, comes out 1.26x with a standard error of 0.009, significant even with three replicates. Every drawn question becomes a group of eight rollouts, and every set runs once on each configuration; across the campaign that comes to 90 questions (3 of them repeated across batch sizes) and 1,440 rollouts.
First, the wasted work, and on this workload the waste lives in prefill. The workers run mlx-lm, plus our own optimizations. In a multi-turn environment most prefilled tokens are repeats. Every turn re-feeds the whole conversation so far, and the eight rollouts of a group share the same question prompt. So we added two cache mechanisms. An episode prefix store, our prefix-caching layer, prefills the shared prompt once per GRPO[1] group and keeps each episode's KV cache alive across turns. Underneath it, a paged-KV cache holds dozens of forked caches with divergent lengths in unified memory without fragmenting it.[19]2
Figure 5 shows what this buys: the prefix store prefills 41% fewer tokens for the same decode work, and completed episodes per hour plateau 25 to 30% higher. And behavior doesn't move. Pass@1 and turns per episode match between the two paths at every batch size. The cache changes throughput, not the policy.
That leaves the batch size. The batch throughput keeps climbing all the way to 128 concurrent sequences, from 200 to 428 tokens per second with no sign of leveling off (Figure 6, left), so if raw throughput were the goal we'd run the biggest batch that fits in memory.
But the aggregate hides what happens to each sequence. Every rollout decodes more slowly as the batch grows, from 12.5 tokens per second per sequence at 16 sequences down to 3.3 at 128, and a sweep that finishes in 486 seconds at 64 sequences takes 978 at 128. That wall-clock time is where staleness comes from. The trainer publishes new versions on its own schedule regardless of what the Macs do, so every extra minute a rollout spends in the batch ages it by another fraction of a version before it's trained on. And episodes per hour saturate anyway. As the batch grows, prefill eats a larger share of each sweep, so past 64 sequences the extra batch throughput buys more aggregate tokens but fewer completed episodes per hour, each of them older (Figure 6, right).
We ran every Mac below its peak throughput on purpose: a bigger batch only ages the rollouts.
So we set the fleet's operating point at 64 sequences, eight groups of eight rollouts. Episodes per hour peak there, and a full sweep still finishes within about one publish interval. One interval is not a magic number: it is the worker's share of a hard three-version staleness budget on the trainer side, and section 6 shows where the other two versions go.
The same rule sets the group count for weaker hardware, because what we hold constant across the fleet is how long a sweep takes, not the batch size. The M2 Pro that joined the fleet late runs four groups (32 sequences) instead of eight, which keeps its sweep time within 1.1 to 1.25 times a full M4 Pro's, roughly the same staleness at about half the episodes per hour. Running it at 64 sequences would raise its throughput and push the rollouts it ships roughly another publish interval into the past. My MacBook, the M3 Pro in the fleet, is the extreme case: 18 GB of unified memory, and the int8 weights take 9 GB of it. It runs a single group of eight, because I kept using the laptop while it worked, and at two groups the memory pressure crashed it. At one, the laptop stays functional and still ships rollouts.
5 · Studying and gating the off-policy gap#
Everything so far has been systems work aimed at keeping the off-policy gap small: weights land in seconds, rollouts ship the moment they exist, and no sweep runs long enough to let them age. But systems can shrink the gap, not close it. Every batch the trainer consumes was still generated a few policy versions earlier,[11][12] on different hardware, with a different inference stack. Now the remaining problem is algorithmic. We study the gap that remains, then keep training stable on it.
The standard way to keep training stable on off-policy data is PPO's clip, and it keys off the importance ratio, the trainer's probability for a token over the Mac's. Figure 7 shows what the clip does with that ratio. It trusts a band within 20% of a ratio of 1, and masks the two corners where the update would push the trainer farther from the Mac. But one corner stays open. When a token's advantage is negative, so the update should lower its probability, but the ratio sits above 1.2, the clip passes the full ratio-weighted update with no upper bound, and a single large ratio can then carry many times the weight of an in-band token. That's the one branch we bound separately, with a dual-clip cap.
Some off-policy gap exists in every RL setup, even the standard one where the inference engine and the trainer share a datacenter,[7][10] so the question isn't whether our setup has a gap. It's how much worse ours is than the one everyone already tolerates. To find out, we ran both setups through the same test. The inference engine generated episodes and logged each sampled token's probability, and the trainer then scored those same tokens. Both arms were frozen at the base checkpoint, so this isolates the inference-stack mismatch from the separate policy-lag part of the production gap. The two probabilities give the ratio the clip reads and the difference the gate reads. The baseline is slime's stock colocated pair, SGLang and Megatron sharing one B200 in bf16. Ours is the Mac fleet's int8 mlx-lm against that same trainer, an ocean away (Figure 8).
Same production rollout path and question pool as the benchmarks above, matched pairs across the two settings. A per-token distribution and its tail need more than a single throughput number, so here we draw 400 questions, matched across both settings, with eight rollouts each per arm. That's 6,400 rollouts in all and about 3.2 million response tokens per arm, from a fixed set we release with the code.
Figure 8 shows the ratio for both setups. Our int8 fleet crosses the ε = 0.2 band on 6.5% of tokens, about twice as often as the colocated baseline's 3.1%, at the same frozen weights. But the ratio is a poor guide to how much the two probabilities actually differ. It's a scale-dependent proxy. A rare token the Mac scored near 10−4 and the trainer near 1.5×10−3 carries a ratio of about 15 while the two probabilities differ by barely 0.001. Those low-probability tokens are where the two inference stacks disagree most, and the ratio turns a tiny difference into a large number. Of the tokens that cross our band, a third differ by less than 0.02 in probability.
So we gate on the gap instead of the ratio. This is DPPO's token gate.[16] Its keep-or-drop decision reads the gap directly, the absolute difference between the trainer's probability for the token and the one the Mac logged at generation, while every kept token stays weighted by the ratio. A rare-token difference stays a small gap, and a real disagreement stays a large one. If the gap exceeds a threshold δ and the update would push the two policies farther apart on the token, DPPO drops it from the loss. A corrective update, one that pulls them back together, is never blocked, however large the gap:
Mt = 0, if Ât > 0 and πθ(yt | st) − μ(yt | st) > δ, 0, if Ât < 0 and μ(yt | st) − πθ(yt | st) > δ, 1, otherwise
L = 1⁄N Σt Mt ℓt
where yt is the token and st its context, μ is the Mac's probability, πθ is the trainer's, Ât is the token's advantage, and Mt is the gate. ℓt is the ratio-weighted policy-gradient loss on that token, with extreme ratios capped by dual-clip at C = 20. N is a fixed token budget in the style of Dr. GRPO,[28] the same for every batch no matter what the gate drops, so gated tokens contribute zero and survivors are never reweighted upward to compensate. On this run δ = 0.2; the remaining loss settings are pinned in the run's launch script.
The gap tells a calmer story. Only 0.08% of our tokens have a gap past δ = 0.2, against 0.03% colocated, and every one of them is already among the 6.5% the ratio flags. The other 6.4% is ratio inflation. The gate drops the subset of that 0.08% where the update would push the two farther apart, and the tokens it keeps stay weighted by the ratio, so the ratio still sets how much each one counts. That's why the open corner from Figure 7 matters, and why the dual-clip cap at C = 20 holds it. Our largest importance weight reached 18.5, just under the cap.
The importance ratio leaves the trust band on 6.5% of our tokens, but only 0.08% actually differ.
Three safeguards handle the rest: a small KL penalty toward a frozen base-model reference,[17] a staleness cutoff for rollouts more than three versions old, and a reuse cap of three training passes per group. Together they keep the trainer stable on data it didn't quite generate.
6 · Keeping both sides busy: how many Macs does one B200 need?#
By now every piece is in place: weights move in seconds, rollouts upload while the sweep still runs, and the gate from the previous section makes slightly-old data safe to train on. What's left is sizing the fleet so neither side waits. Three limits set the terms: the trainer publishes a version every four optimizer steps, a group older than three versions is rejected, and a group is trained on at most three times. Whether either side ever waits depends on how the fleet's production measures up against the trainer's demand under those limits, and that is what this section explores.
Each optimizer step consumes 32 groups, all or nothing. If fewer are eligible, the trainer waits. The replay buffer serves groups the trainer has never used, newest first, then fills the rest with reuse. A group counts as fresh only on that first use, and there is no minimum share of fresh data per batch.
Staleness is counted in versions: a group is one version old when one new version has published since it was generated, and the trainer rejects any group past three. A typical group is about two versions old when it trains, roughly eight optimizer steps. Almost none of that comes from the Macs. Generating a group and getting it to the bucket costs under one version, because section 4 sized a sweep to finish inside one publish interval. The other version or so is added on the trainer's side, waiting in the replay buffer and being reused.
The staleness the trainer sees comes mostly from its own replay buffer, not the Macs or the network.
The numbers from here on are not benchmarks. They're telemetry from the production run itself, the fourteen-Mac run from the introduction.
So how did production measure up against demand on the live run? Almost exactly at balance. Each training batch came out 51% fresh groups and 49% reused, so the fleet was producing new groups at very close to the rate the trainer drew them down. The eligible pool sat at a median of 111 groups against the 32 a step draws, and staleness held near 2 versions under the cap of 3 (Figure 9). Reuse is the slack. It lets a fleet sized to fresh demand feed a trainer that never idles, filling out each batch with recent groups when new ones arrive a little behind.
So how long did the trainer actually wait? On three steps of every four, 1.8 seconds, flat across the run. Every fourth step logs about 18 seconds, but 16.5 of those are the checkpoint export that feeds the weight publish, not the trainer sitting idle for data. The rhythm is the price of publishing, not starvation.
So how many Macs does one B200 need? The count is really a dial between two failure modes. Too few and the trainer drains its buffer and idles between steps; too many and rollouts sit waiting and go stale past the cap before they're trained on. The right number is the one that keeps both small at once, where fresh production just meets the trainer's demand. For this model and fleet that was thirteen to fourteen. At that balance the communication-computation overlap is nearly total: a Mac exposes two to four seconds of weight pull per eight-minute sweep, uploads hide under decode, the trainer's downloads hide under its steps, and the only synchronous cost left is the 16.5-second export. In this system, communication is paid in versions, not seconds; and the gate is what made them safe to spend. Whether any of this taught the model anything is the last question.
7 · Agentic search results: held-out pass@1, 29% to 63%#
None of this matters if the model didn't learn. We chose PaperSearchQA[14] as the environment because it's easy to grade but carries the real complexity of an agentic setup: tool calls, multiple turns, and decisions about when to use them. The model answers biomedical questions by searching a corpus of 16 million paper abstracts, in the style Search-R1 introduced.[15] The model reads a question, decides whether to search, reads what comes back, and commits an answer; the reward is simple: an episode counts as a success if the reference answer appears in the model's final answer, and that same rule is how we score every result below. The full configuration, every hyperparameter and flag, is in the run's launch script, released with the code.
On held-out questions the model never saw, pass@1 went from 29% to 63% and pass@8 from 60% to 83% (Figure 10). The search behavior held as well: at the final eval checkpoint the model chose to search on 83% of held-out questions rather than answering from memory (90% at its peak). We report the run through its 100th published weight version; by then the held-out gain had slowed to about half a point of pass@1 per ten versions. That 100th version landed at step 444, not 400: publishing waits on the previous export and upload, so versions ran 4.44 steps apart instead of the planned four.
That search behavior did not come for free. The model came in biased toward answering directly. Early on its held-out search rate was just 22%, and even on the questions that need a corpus lookup it searched only about a quarter of the time. A correct answer earns the same reward whether the model searches or recalls, and recall gets there in fewer turns, so most of the rollouts the fleet produced were direct answers, and that's what the trainer learned from. In an early run, search collapsed to one-turn answers from memory.
The data mix was what fixed it. We weighted the training mix 75/25 toward questions that need a lookup, so most of the questions could only be answered by searching and recall stopped being the easy path to the reward. We also guarded against a second cause. A searched episode runs longer than a recalled one, and GRPO's per-response length normalization lets an episode's length change how much its tokens count, so length alone could have nudged the policy toward the short recalled answer. We switched to the Dr.GRPO loss,[28] whose constant denominator drops that normalization, so a long searched episode is no longer weighted against a short recalled one just for being long. It worked. The model learned to be selective, searching when a question needs the corpus and answering from memory when it does not, and the search rate held high the whole way (Figure 11).
Search and recall earn the same reward, so the model quit searching — until we changed the data mix.
One thing the run turned up surprised us: the deltas came out even smaller than the PULSE paper predicted. The paper measured about 1% of weights crossing the int8 grid per optimizer step at bf16;[13] our grid is coarser, and even with four steps folded into every version, the median version moved just 0.55% of the weights. The int8 cast that saves the Mac its memory bought extra compression on top. Figure 12 shows the deltas holding that small across the whole window, optimizer steps 1 through 444.
8 · Conclusion#
This is the first ever post-training run we're aware of where the rollout side was consumer Macs and nothing else, with no rollout ever touching a datacenter GPU. And the run held up. The training-inference mismatch cost about 0.3% of tokens in steady state, gated at the int8/bf16 boundary; the three-version cutoff kept rollout age bounded; and held-out pass@1 more than doubled, from 29% to 63%. Measured end to end, the missing high bandwidth appeared to have no notable effect. We ran it to test the system and showcase the library release. We stopped at 14 Macs because that's what one B200 could consume, not because the fleet has a ceiling. For a model that fits on one Mac, thousands could join.
Everything we built is open source at github.com/PluralisResearch/stoa, down to the native paged-attention kernels and the port that lets Megatron train LFM2.5's MoE architecture. Three limitations remain: each Mac still holds the whole model, so we can train only models that fit on one Mac; the trainer is still limited to a single cluster; and Stoa doesn't yet make the resulting model unextractable, so that no single participant can pull the full weights out of the swarm.[29]
Agora, Pluralis's decentralized-training machine and distributed trainer, has already demonstrated the distributed big-model capability Stoa lacks by pretraining Pluralis-8B across hundreds of consumer GPUs over the open internet. As far as we can tell, it was the first run of its kind over a WAN.[24] That result builds on prior work compressing what crosses each link.[20] Unextractability comes from Pluralis's separate Protocol Models work, not that live run, and makes the model protocol-owned rather than owned by any one party. Stoa is one piece of Agora: the post-training stack we built around the trainer, including the inference fleet, weight sync and communications, and the RL loop. Our next step is to bring Agora's distributed big-model training and Protocol Models' unextractability into Stoa over the open internet, with no datacenter in the middle. We'll build both in the open.
The addressable pool of idle owned silicon is at datacenter scale. Between them, Agora and Stoa can reach roughly 3 GW of idle consumer NVIDIA GPUs and around 5 GW of idle Apple silicon, roughly 8 GW in all, on the scale of the largest training datacenters being built today (Figure 13).
That scale matters because the strongest models are moving behind closed APIs. Training costs this large concentrate capability in a few firms.[23] So the open path is fragile and closing. Leading US labs already restrict their models by region,[31] and China is weighing a silicon curtain around its most sought-after models.[32] Using any of them hands your own knowledge back to a few providers, companies and individuals alike. Training the strongest models on hardware people already own, owned by the people who train them, is how we keep a door open. That's what we stand for at Pluralis.
Pluralis's goal is to move us away from a scenario where the most impactful technology humanity has, or ever will develop, is siloed and controlled by very few entities. We don't think regulation is the answer, because it simply moves control from one group to another. Instead, we want to disperse productive capacity, the ability to actually create and develop models, as broadly as possible. Core to this vision is assembling computational power that's already distributed so it can be useful for model creation. This is the underlying motivation of our Protocol Learning vision.[30]
Citation#
Please cite this work as:
Or use the BibTeX citation:
References#
- Shao, Z., Wang, P., Zhu, Q., et al. (2024). DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. arXiv:2402.03300.
- Liquid AI. (2026). LFM2.5-8B-A1B: An Even Better On-Device Mixture of Experts. Liquid AI blog; Hugging Face model card.
- Hannun, A., Digani, J., Katharopoulos, A., et al. (2023). MLX: Efficient and flexible machine learning on Apple silicon. github.com/ml-explore/mlx.
- Shoeybi, M., Patwary, M., Puri, R., et al. (2019). Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism. arXiv:1909.08053.
- He, J., Li, T., Feng, E., et al. (2026). History Doesn't Repeat Itself but Rollouts Rhyme: Accelerating Reinforcement Learning with RhymeRL. ASPLOS 2026. arXiv:2508.18588.
- Zhou, Y., Li, J., Su, Y., et al. (2025). APRIL: Active Partial Rollouts in Reinforcement Learning to Tame Long-tail Generation. arXiv:2509.18521.
- Yao, F., Liu, L., Zhang, D., et al. (2025). Your Efficient RL Framework Secretly Brings You Off-Policy RL Training. Blog post.
- Geerling, J. (2025). 1.5 TB of VRAM on Mac Studio – RDMA over Thunderbolt 5. jeffgeerling.com.
- EXO Labs (Cheema, A.). (2024). exo: run your own AI cluster at home. github.com/exo-explore/exo; December 2024 demo post.
- He, H. (Thinking Machines Lab). (2025). Defeating Nondeterminism in LLM Inference. Blog post.
- Noukhovitch, M., Huang, S., Xhonneux, S., et al. (2025). Asynchronous RLHF: Faster and More Efficient Off-Policy RL for Language Models. ICLR 2025. arXiv:2410.18252.
- Wu, B., Wang, S., Tang, Y., et al. (2025). LlamaRL: A Distributed Asynchronous Reinforcement Learning Framework for Efficient Large-scale LLM Training. arXiv:2505.24034.
- Miahi, E., & Belilovsky, E. (2026). Understanding and Exploiting Weight Update Sparsity for Communication-Efficient Distributed RL. arXiv:2602.03839.
- Burgess, J., Hansen, J. N., Peng, D., et al. (2026). PaperSearchQA: Learning to Search and Reason over Scientific Papers with RLVR. EACL 2026. arXiv:2601.18207.
- Jin, B., Zeng, H., Yue, Z., et al. (2025). Search-R1: Training LLMs to Reason and Leverage Search Engines with Reinforcement Learning. COLM 2025. arXiv:2503.09516.
- Qi, P., Zhou, X., Liu, Z., et al. (2026). Rethinking the Trust Region in LLM Reinforcement Learning. arXiv:2602.04879.
- Ouyang, L., Wu, J., Jiang, X., et al. (2022). Training Language Models to Follow Instructions with Human Feedback. NeurIPS 2022. arXiv:2203.02155.
- Cloudflare. (2026). R2 documentation: pricing. developers.cloudflare.com/r2/pricing.
- Kwon, W., Li, Z., Zhuang, S., et al. (2023). Efficient Memory Management for Large Language Model Serving with PagedAttention. SOSP 2023. arXiv:2309.06180.
- Ramasinghe, S., Ajanthan, T., Avraham, G., et al. (2025). Subspace Networks: Scaling Decentralized Training with Communication-Efficient Model Parallelism. NeurIPS 2025. arXiv:2506.01260.
- Benazir, A., & Lin, F. X. (2026). Benchmarking and Characterization of Large Language Model Inference on Apple Silicon. SIGMETRICS 2026. arXiv:2508.08531.
- Javat, A., & Kazakov, A. (2026). Silicon Showdown: Performance, Efficiency, and Ecosystem Barriers in Consumer-Grade LLM Inference. arXiv:2605.00519.
- Vipra, J., & Korinek, A. (2023). Market Concentration Implications of Foundation Models: The Invisible Hand of ChatGPT. Brookings.
- Pluralis Research. (2026). Agora: pipeline-parallel pretraining over the public internet. agora.pluralis.ai; Pluralis-8B completion announcement.
- Ookla. (2026). Speedtest Global Index. speedtest.net/global-index.
- Dillet, R. (2018). There are now 100 million Macs in use. TechCrunch.
- Piché, A., Kamalloo, E., Pardinas, R., et al. (2026). PipelineRL: Faster On-policy Reinforcement Learning for Long Sequence Generation. TMLR 2026. arXiv:2509.19128.
- Liu, Z., Chen, C., Li, W., et al. (2025). Understanding R1-Zero-Like Training: A Critical Perspective. COLM 2025. arXiv:2503.20783.
- Long, A., Hewa Koneputugodage, C., Ajanthan, T., et al. (2025). Unextractable Protocol Models: Collaborative Training and Inference without Weight Materialization. NeurIPS 2025. arXiv:2605.23464.
- Long, A. (2025). A Third Path: Protocol Learning. Pluralis Research.
- Anthropic. (2025). Updating restrictions of sales to unsupported regions. anthropic.com.
- Reuters. (2026). China weighs silicon curtain around sought-after AI models. reuters.com.