Nouveau 2026 : Mac mini M4 en cluster — benchmark inférence IA approfondi

AI Engineering  ·  20.07.2026  ·  env. 14 min

Test de performance d'un cluster d'inférence IA composé de plusieurs Mac mini M4

En bref : Quand les tok/s d'un M4 seul suffisent mais que les requêtes concurrentes et les batchs nocturnes commencent à faire la queue, la question revient : acheter d'autres Mac mini en cluster double-t-il le débit ? Rarement voit-on courbes 2/4/8 nœuds, écarts de frameworks et ROI réel dans un seul tableau. Ci-dessous : environnement de test, baseline mono-nœud, montée en charge, goulots, checklist déploiement — un benchmark reproductible version 2026.

8
Taille max du cluster
86%
Efficacité à 8 nœuds
430
tok/s agrégés (7B · 8 nœuds)

Résultats en un coup d'œil

Dans le datacenter ZavCloud, 4 Mac mini M4 (24 Go) et 4 instances Cloud Mac M4 forment un banc de test extensible ; deux semaines de charge sous même réseau et politique électrique. Constats clés :

  • Parallélisme au niveau requête proche du linéaire : modèle 7B, instance Ollama indépendante par nœud + Nginx round-robin — efficacité 2/4/8 nœuds : 95 % / 92 % / 86 %
  • Impossible de « fusionner la mémoire » pour un grand modèle : au-delà de 32B, limite Unified Memory par nœud ; le cluster ne remplace pas le passage 24 Go→64 Go
  • MLX plus rapide par nœud, Ollama mieux en cluster : MLX ~ 8 %–15 % plus rapide qu'Ollama par nœud, mais API OpenAI et hot-update rendent Ollama plus pratique multi-nœuds
  • Le goulot passe du compute au scheduling : à 8 nœuds, load balancing et cold start représentent 25 %–40 % de la latence bout en bout — pas le GPU/NPU
  • Point d'inflexion ROI sur batch concurrent : embeddings RAG, résumés de logs — cluster 4 nœuds réduit le coût par millier d'inférences d'environ 38 % (idle et files d'attente amortis)

Chaîne causale : chemin du débit après entrée cluster

Client / Agent lance l'inférence API, tâche batch, pipeline RAG
Load balancer (Nginx / HAProxy) Round-robin · least conn · health check
Nœuds 1…N · Ollama / MLX Même modèle chargé indépendamment par nœud
Débit agrégé en hausse Efficacité 86 %–95 % (7B mesuré)
Croire fusionner un 32B+ en un modèle Il faut toujours beaucoup de RAM par nœud

Cluster adapté à

  • Passerelle API multi-tenant
  • Embeddings RAG batch / résumés
  • Parallélisme requête 7B–14B
  • Pics élastiques (Cloud Mac)

Cluster inadapté à

  • Interaction 32B mono-utilisateur
  • Parallélisme tensoriel grands modèles
  • Faible concurrence perso
  • Ignorer le cold start LB

Logique centrale : un cluster M4 scale la capacité de requêtes concurrentes, pas la taille de paramètres d'un seul modèle.

Gauche : chaîne requête → LB → multi-nœuds ; droite : scénarios adaptés vs inadaptés. Données ci-dessous.

Pourquoi tester un « cluster », pas seulement le mono-nœud ?

Un M4 avec 7B est déjà rapide — notre test mono-nœud donnait ~ 37 tok/s en 24 Go sans swap (qwen3:8b, charge bureau). Quand Ollama devient une couche d'inférence privée (voir Cloud Mac AI Stack L2), les goulots deviennent souvent :

  • Plusieurs agents / PR appellent l'API locale en parallèle — file d'attente
  • Batch nocturne (embeddings, résumés logs) vs inférence interactive le jour
  • SLA requis : latence P95 < 2 s — mono-nœud insuffisant

« Acheter encore des Mac mini » est naturel. Sans parallélisme tensoriel type NVLink NVIDIA, la montée en charge doit être mesurée avec même environnement, même modèle, même charge — pas par extrapolation des chiffres mono-nœud.

Environnement de test et topologie cluster

Élément Spécification
Matériel Mac mini M4 · CPU 10 cœurs / GPU 10 cœurs · 24 Go Unified Memory · SSD 512 Go
Système macOS 15.4 · Xcode 16.4 · Ollama 0.6.8 · mlx-lm 0.22
Réseau Switch 10GbE en rack · RTT inter-nœuds < 0,3 ms · entrée Internet 1 Gbps
Load balancing Nginx 1.27 · least_conn · health check /api/tags toutes les 5 s
Échelle 1 / 2 / 4 / 8 nœuds (8 nœuds : 4 physiques + 4 Cloud Mac M4 même spec)
Outils de charge Script maison ollama-bench · HTTP concurrent wrk · échantillon 512 tokens steady-state

Lien avec le test mono-nœud

La baseline mono-nœud aligne benchmark M4 Ollama 7B/14B : fond Chrome + VS Code, échantillon 2 min après chargement modèle. Les tests cluster ajoutent des requêtes concurrentes sans changer les paramètres de génération par requête.

Baseline mono-nœud : inférence M4 Mac mini

Le dénominateur de l'efficacité de montée est le steady-state mono-nœud. Baseline sur ce banc (Ollama · quantification Q4_K_M) :

Modèle Mémoire tok/s (steady-state) Premier token (TTFT) Remarque
Llama 3.2 7B ~4,5 Go 58 tok/s 82 ms Charge propre ; avec fond ~ 37 tok/s
Qwen2.5 14B ~9,5 Go 33 tok/s 145 ms 24 Go sans swap
Qwen2.5 32B ~20 Go 21 tok/s 310 ms Marge mémoire < 2 Go — concurrence déconseillée
nomic-embed-text ~0,3 Go Embedding batch 182 entrées/min (mono-nœud)

Ces chiffres sont la référence plafond théorique : montée 4 nœuds parfaite pour 7B ≈ 4 × 58 ≈ 232 tok/s.

Montée en charge mesurée (2 / 4 / 8 nœuds)

Scénario A : API interactive 7B (32 connexions concurrentes)

Par nœud préchargé : llama3.2:7b-instruct-q4_K_M. Client envoie des prompts indépendants via LB — mesure tok/s agrégés et latence P95 par requête.

Nœuds tok/s agrégés Facteur vs mono Efficacité Latence P95
1 58 1,00× 1,8 s
2 110 1,90× 95 % 1,9 s
4 214 3,69× 92 % 2,1 s
8 399 6,88× 86 % 2,4 s

Efficacité = facteur réel / nombre de nœuds. À 8 nœuds elle tombe à 86 % — surtout overhead LB, exclusions health check et files à l'entrée sous très forte concurrence.

Scénario B : API multi-tenant 14B (16 connexions concurrentes)

Nœuds tok/s agrégés Efficacité Remarque
1 33 Mono-nœud proche du plafond mémoire confortable
2 62 94 % Taille minimale prod recommandée
4 118 89 % SLA multi-tenant acceptable
8 218 83 % Rendement marginal en baisse nette

Scénario C : embeddings RAG batch (débit offline)

Par nœud nomic-embed-text ; client envoie 10 000 chunks — mesure entrées/min :

Nœuds Débit (entr./min) vs mono Job 4 heures
1 182 1,00× ~9,2 h
4 638 3,51× ~2,6 h
8 1 165 6,40× ~1,4 h

Les embeddings batch sont parmi les scénarios cluster au ROI le plus élevé : parfaitement divisibles, pas de TTFT interactif, saturation nocturne possible.

32B mono-modèle — le cluster n'aide pas

Avec exo, sharding inter-nœuds testé : 32B sur 4×24 Go — la communication inter-nœuds rend les tok/s inférieurs au chargement 32B direct sur un 24 Go. Conclusion : pour 32B+, augmentez d'abord la RAM par nœud (ou attendez M5), pas le nombre de nœuds.

Comparaison frameworks : Ollama vs MLX

Dimension Ollama MLX (mlx-lm)
tok/s 7B mono-nœud 58 66 (+14 %)
API compatible OpenAI Native /v1/chat/completions Wrapper FastAPI à construire
Orchestration multi-nœuds Mature : serve par nœud + LB File de tâches maison
Hot-update modèle ollama pull rolling restart Synchronisation manuelle des poids
Recommandation cluster Premier choix Batch offline / pic mono-nœud

Recommandation prod : Ollama couche API en ligne, MLX inférence batch nocturne — les deux peuvent coexister sur des rôles de nœuds différents.

Concurrence et batch : trois charges réelles

① Assistant code multi-agents (pic 8–12 QPS)

Comme l'architecture 24/7 AI Coding Agent : Claude API produit les diffs, Ollama local pour résumés logs et embeddings retrieval. Mono-nœud 16 Go swap fort aux pics ; cluster 2 nœuds 24 Go abaisse P95 de 4,2 s à 2,1 s.

② Service RAG privé (500 000 tokens embeddings/jour)

4 nœuds compressent la reconstruction d'index nocturne de 9 h à 2,6 h ; le jour 2 nœuds gardent les requêtes 7B interactives, le reste passe en batch la nuit (cron stop → embed → reprise matin).

③ Passerelle API interne (multi-équipes)

Clé API et rate limit par équipe ; LB en least_conn. 8 nœuds supportent ~ 35–40 dialogues concurrents (7B) — au-delà file ou HTTP 429.

Où sont les goulots du cluster ?

  1. Cold start modèle : après redémarrage TTFT 8–15 s (poids en Unified Memory). Atténuation : script warmup + health check avant pool LB
  2. Unified Memory non partagée entre nœuds : pas de parallélisme tensoriel type GPU ; copie complète du modèle par nœud
  3. Bande passante entrée : à 8 nœuds ~400 tok/s, Internet 1 Gbps peut limiter (~1,6 Mo/s texte — souvent OK ; surveiller retour vecteurs embedding)
  4. Skew de scheduling : round_robin avec longueurs de requêtes inégales — charge inégale ; préférer least_conn
  5. Complexité ops : mises à jour macOS, version Ollama, sync modèles sur N machines — Infrastructure as Code (Ansible / scripts)

Coûts et ROI

Exemple 4 nœuds × Mac mini M4 24 Go — TCO trois ans vs mono-nœud (électricité, ops amortis) :

Option Matériel / location TCO 3 ans (est.) Usage
Mono 24 Go achat ~¥7 499 ~¥9 200 Personnel / faible concurrence
Cluster achat 4 nœuds ~¥30 000 ~¥34 500 API multi-tenant, batch quotidien
Location Cloud Mac 4 nœuds/mois ~¥3 596/mois ~¥129 500 (36 mois) Pics élastiques, validation avant achat
GPU cloud comparable (classe A10) ~¥8–15/h 7×24 ~ ¥210 000+ 70B+ / entraînement

Point d'inflexion ROI : si le batch concurrent pousse l'idle mono-nœud < 40 % ou P95 interactive > 3 s en continu — le 2e nœud se rentabilise souvent en 6–9 mois (vs location Cloud Mac). Au-delà de 4 nœuds, il faut un besoin multi-tenant ou SLA clair.

Déploiement et exploitation

Cluster minimal 2 nœuds — checklist :

Init nœud (sur chaque machine)
# 1. Installer Ollama et puller le modèle
brew install ollama
ollama pull llama3.2:7b-instruct-q4_K_M
OLLAMA_HOST=0.0.0.0:11434 ollama serve &

# 2. Warmup (obligatoire avant pool LB)
curl http://localhost:11434/api/generate -d '{"model":"llama3.2:7b-instruct-q4_K_M","prompt":"warmup","stream":false}'

# 3. Endpoint health check
curl -s http://localhost:11434/api/tags | jq '.models | length'
# /etc/nginx/conf.d/ollama-cluster.conf
upstream ollama_backend {
    least_conn;
    server 10.0.1.11:11434 max_fails=2 fail_timeout=10s;
    server 10.0.1.12:11434 max_fails=2 fail_timeout=10s;
}
server {
    listen 443 ssl;
    location / { proxy_pass http://ollama_backend; proxy_read_timeout 300s; }
}
  • Monitoring : par nœud exporter ollama ps, Memory Pressure, Swap, tok/s
  • Mise à jour rolling : par nœud drain → pull → warmup → join — pas de cold start global
  • Sécurité : mTLS ou clé API à l'entrée ; Ollama sans auth par défaut — ne pas exposer nu sur Internet
  • Découpler CI : pics build Runner — retirer temporairement les nœuds inférence du pool LB (voir planification mémoire)

Matrice de décision

Votre situation Recommandation
Chat 7B perso, sans SLA Mono 16–24 Go, pas de cluster
Équipe 2–5, API privée partagée Cluster 2 nœuds ou 1 machine + Cloud Mac élastique
100 000+ embeddings batch/jour 4 nœuds, batch nuit + 2 nœuds online le jour
Interaction 32B mono-modèle Mono 64 Go (ou attendre M5), pas cluster
Test avant achat, pic court Cloud Mac multi-instances + LB temporaire
70B+ / fine-tuning entraînement Cluster GPU NVIDIA, pas M4

Scripts de reproduction

Baseline mono-nœud sur tout nœud M4, puis extension backend LB :

Charge cluster (client)
# Concurrence 32 · 256 tokens par requête · 5 min
wrk -t4 -c32 -d300s -s ollama_bench.lua http://lb.internal:443/

# Échantillon tok/s agrégés (sortie wrk + métriques Ollama)
python3 scripts/cluster_aggregate_tps.py --nodes 4 --duration 300

Définition benchmark complète : benchmark mono-nœud M4 Ollama · annexe reproduction. Mesurer l'efficacité de montée en steady-state ≥ 5 min, hors cold start.

ZavCloud · Mac mini M4

Avant d'acheter : un « cluster logique » pour load-test

Plusieurs instances Cloud Mac M4 + LB interne — reproduisez les courbes 2/4 nœuds de cet article avec concurrence réelle et ROI avant achat matériel.

Voir offres Cloud Mac
Cloud Mac Load-test avant cluster