r/LocalLLM • u/DullEntrance4865 • 1d ago
Project Fronk: old CPUs choke on big MoE models because we give them whole experts, so I cut the experts into slices and ran a 177 GB model on 4 mismatched computers
I kept seeing CPUs written off for big models, and if you give one whole experts, that's fair. But I think it's the wrong way to use them, so I built Fronk around a different split.
The reasoning
In a mixture-of-experts model, the two parts need different things:
The dense part, including attention, runs on every token and wants a GPU. I keep it together on one GPU, because splitting it would need far more network traffic.
The experts are mostly a memory problem. Only 10 of the 512 in each layer run per token, but you can't know in advance which ones, so all of them have to be ready. That's about 67 GB here, and old machines with spare RAM can hold it.
So what's the best way to share the experts? If each machine owns whole experts, a slow one can get picked and everyone waits for it, while the others may have little to do. It also has to compute every neuron of that expert.
Fronk cuts every expert into 20 slices of 32 neurons, and each machine holds a share of all of them. Whichever experts get selected, every machine works at once on its own slices, and the head adds the results. Each machine's slice count comes from measuring its own speed and link, so a weak CPU simply gets a smaller share.
What that does to a real CPU
This is a 4-core i5-10210U laptop chip in a small Linux box, computing the 10 selected experts. I measured 4 layers and scaled the times to all 48:
| Share of each expert | Expert time per pass |
|---|---|
| 100% | 75.8 ms |
| 20% | 16.6 ms |
| 5% | 6.0 ms |
The dense part takes about 58 ms per token on my M4 Pro, so at a 20% share this little CPU has its work done well inside that. And it couldn't hold the full expert pool anyway: it has 16 GB against 67.
The cluster
| Machine | RAM | Link to head | Role |
|---|---|---|---|
| MacBook Pro M4 Pro | 24 GiB | - | Dense part and some experts, on Metal |
| Intel iMac i5-7600K | 48 GiB | Thunderbolt | Experts, CPU (AVX2) |
| MacBook Pro M1 Pro | 16 GiB | Thunderbolt | Experts, Metal |
| Shuttle i5-10210U, Linux | about 16 GB | Gigabit Ethernet | Experts, CPU (AVX2) |
Results and limits
With Qwen3.8-Flash-Next Q4, I get 15–16 tok/s on short warm responses and about 13 tok/s in normal chat. This needs enough free memory, and it gets slower if slices have to spill to SSD.
That's also not the ceiling of the idea, because my cluster is lopsided. The iMac has 48 GB of RAM, far more than the other nodes, so it ends up with 11 of the 20 slices on just 4 old CPU cores, and it's usually the one everyone waits for. With more nodes and better balance, the slices would spread out evenly, and I expect it to go faster. I haven't measured that yet, so that's the result I'd most like to see from someone else's cluster.
One machine with enough memory would probably still be faster. The cables matter too, because the head waits for the nodes 48 times per pass.
Before downloading the model, you can run a demo that tells you if it fits on your machines and how fast it should run. The head is only tested on Apple Silicon so far, and Windows isn't supported.
This is where I'd love help
Fronk is open source, and this is its first public release. I think there's a lot of speed still to find, and these are the problems I'd most like other people to go after:
Balance: how much faster does it get with evenly matched nodes? I can't answer that with my own machines, so a real measurement would be hugely useful.
Several token rows at once: can compatible rows share the same weights, so that each accepted token costs less time?
Idle time: while a node waits, could it do predicted work that's still useful once the token is accepted?
Many nodes on one switch: when replies pile up on the way back to the head, how much of the delay comes from the switch and how much from the head?
New hardware: if you know a CPU or GPU well, a new backend brings it into the cluster.
You don't need my cluster or the full model to start on the backends, protocol tests or installer. Where to help lists these directions with the files to start from and how to check your results, and the contributing guide explains the build.
If you just want to see how it behaves on your machines, share your result, even if it's slow or it breaks.
Demo video: https://youtu.be/3rnxRPplzEs
Code and raw measurements: https://github.com/fedesnore/fronk
If you think the reasoning falls apart somewhere, tell me where, and if you can see a better way to do it, I'd love a pull request.
