Valg af filsystem til AI-servere: XFS, ZFS, ext4 og hvorfor Btrfs ikke er på listen

Hvis du lige har brugt €40 på GPU'er, fortjener det filsystem, du hælder dine data på, mere end fem minutters overvejelse. Ubuntu-installationsprogrammet lægger gladeligt ext4 på tværs af alt; for mange AI-arbejdsbelastninger er det det rigtige svar, for nogle er det ikke. Vælg det forkerte filsystem til en datasætvolumen på 50 TB, og du mister gennemløb, mister data eller ser din DataLoader sidde inaktiv bag en metadata-flaskehals.

Dette dækker hvilket filsystem der skal placeres hvor på en Kentino-klasse AI-server (4-8 GPU'er, NVMe-opstart, NVMe scratch, langsommere bulk-niveau). Ubuntu 22.04 / 24.04, 6.x kerne.

Den korte version

Monteringspunkt arbejdsbyrde Filsystem Hvorfor
/ (opstart, rod) OS, pakker, logfiler ext4 Kedeligt, bevist, genopretteligt
/scratch (NVMe RAID0) Aktive træningsskår, flygtige skriverier XFS Gennemløb, parallel mappe-I/O
/data (RAID10) Træningsdatasæt, modelkontrolpunkter XFS eller ZFS XFS for rå hastighed; ZFS hvis du vil have snapshots + checksummer
/archive (RAID-Z2/6) Færdige kørsler, kold opbevaring af datasæt ZFS Komprimering, checksummer, snapshots
/home Brugerhjem, notesbøger ext4 Små filer, lav konkurrence

Version med ét afsnit: ext4 til operativsystemet, XFS til hot scratch, ZFS hvor integritet er vigtigere end de sidste 10% af gennemløbet, ingen Btrfs i produktion.

ext4 — den kedelige standardværdi, der normalt er rigtig

ext4 har været standard på Ubuntu, Debian, Fedora og RHEL i over et årti. Velforstået, kan gendannes med fsck, 16 TB pr. fil, 1 EB pr. volumen. Intet spændende — pointen.

Brug ext4 til root (alle Ubuntu live USB ved, hvordan man retter det; langt færre ved, hvordan man importerer en zpool), f.eks. /homeog til VM-billedlagre i lille til mellemstor skala.

Hvor ext4 ikke længere har ret: bred parallel I/O (dens journal serialiserer metadataopdateringer — tyve DataLoader-arbejdere på én ext4-volumenflaskehals i journalen længe før den mætter NVMe); enkelte store filer (håndteres, men extent-allokering er mindre brugervenlig end XFS for sekventielle filer >100 GB — træningsshards, checkpoints, videokorpora); snapshots (ingen native; LVM-tynde snapshots fungerer, men er klodsede).

mkfs.ext4 -L root /dev/nvme0n1p2

Hvis du finder dig selv i gang med eksotisk ext4-tuning til en AI-arbejdsbelastning, har du valgt det forkerte filsystem.

XFS — det rigtige svar til hot scratch- og træningsdata

XFS var et SGI-filsystem til sekventiel I/O med høj kapacitet på store arrays. Denne arv matcher næsten perfekt AI-arbejdsbelastninger: store filer (træningsshards, parquet, webdataset-tars, checkpoints), sekventielle læsninger, mange parallelle læsere, tolerance for "arbejdsbelastningen regenererer dataene".

Hvad XFS gør, som ext4 ikke gør: allokeringsgrupper — volumenet opdeles i 4-32 uafhængige grupper, der læser og skriver parallelt uden en global journallås, præcis hvad en DataLoader med flere medarbejder ønsker; forsinket og spekulativ forhåndsallokering så store sekventielle skrivninger får sammenhængende omfang; ingen praktisk grænse for filstørrelse (8 EB); og xfs_growfs for pålidelig one-liner-udvidelse efter RAID-vækst.

Hvad den ikke gør: ingen native snapshots, ingen fildata-checksums (metadata CRC-beskyttet siden 2014), ingen krympning - kun voksning.

En rimelig mkfs.xfs for en 8× NVMe RAID0 scratch-volumen, 64 KiB chunk:

# su = stripe unit = chunk size; sw = number of data disks
mkfs.xfs -f -d su=64k,sw=8 -l size=512m -L scratch /dev/md0

# largeio + swalloc: behave for >1 MB I/O
# allocsize=1g: preallocate aggressively for big sequential writes
# noatime: save a write per read under heavy DataLoader load
mount -o noatime,largeio,swalloc,allocsize=1g /dev/md0 /scratch

noatime og largeio betyder mest. XFS på små filer er acceptabelt, men ikke dets stærke side — for hundredvis af millioner af billeder på <16 KB, pak om til webdataset / parquet / lmdb i stedet for at bytte filsystemer (se nedenfor).

ZFS — det rigtige svar, når integritet, snapshots eller komprimering er vigtige

ZFS er et filsystem, en volumenhåndtering og et software-RAID-lag i ét:

  • End-to-end checksumming. Bitrot registreret ved læsning, korrigeret lydløst med redundans. For et 50 TB datasæt på spinning rust i to år er dette vigtigt; for kortvarig NVMe scratch i over seks uger er det ikke relevant.
  • Snapshots og kloner. Atomic, COW, effektivt fri. Snapshot før en kørsel, forgrening af en klon, rollback – den arbejdsgang ZFS eksisterer for.
  • Indbygget kompression. lz4 standard-til; zstd for bedre forhold. På tekst / JSON / parquet er komprimering normalt stigninger effektiv gennemløbshastighed, fordi CPU-omkostningerne er mindre end den sparede I/O.
  • ARC — sin egen RAM-baserede læsecache, adskilt fra Linux-sidecachen. Den berømte footgun.
  • Native RAID-Z — nej mdadm.

Hvad det ikke gør godt for AI: spiser RAM (standard ARC er ~50% af systemhukommelsen — på en 512 GB server, der er 256 GB, har kernen pludselig ikke mere, og træningsjob, der forventer sidecache eller store sider, bliver OOM-dræbt; læg en grænse for ARC'en); ikke den hurtigste for rå sekventielle læsninger (veltunet XFS på NVMe RAID0 slår ZFS med 15-30% — checksumming og COW-omkostninger i reelle cyklusser); ignorerer O_DIRECT (al I/O via ARC efter design — fint til de fleste arbejdsbelastninger, en hård inkompatibilitet med GPUDirect Storage).

ARC-tuning — den ene knap, du skal indstille

På en frisk Ubuntu + ZFS-installation på en 512 GB-boks gør ZFS krav på 256 GB til ARC. zfs_arc_max ved installation, ikke efter den første OOM.

# Cap ARC at 64 GB. Bytes, not GB. 64 * 1024^3 = 68719476736
echo "options zfs zfs_arc_max=68719476736" | sudo tee /etc/modprobe.d/zfs.conf
echo 68719476736 | sudo tee /sys/module/zfs/parameters/zfs_arc_max   # apply now
sudo update-initramfs -u                                             # persist

Tommelfingerregel: Begræns ARC til 10-20% af system-RAM på en AI-server. Den klassiske størrelsesorden "2 GiB base + 1 GiB pr. TiB" er til storage boxes; på en AI-box er det meste RAM reserveret til modelvægte, aktiveringer og framework-sidecache.

Et fornuftigt ZFS-layout til et AI-serverdatalag

# 8 × 16 TB SAS in two RAID-Z2 vdevs (6+2 each) — two vdevs give 2× IOPS
zpool create -o ashift=12 \
  -O compression=zstd -O atime=off -O xattr=sa -O recordsize=1M \
  data \
  raidz2 /dev/sd[a-h] \
  raidz2 /dev/sd[i-p]

# Datasets sized for their workload
zfs create -o recordsize=1M   data/datasets       # large training shards
zfs create -o recordsize=128k data/checkpoints    # mixed size
zfs create -o recordsize=16k  data/metadata       # small files (json, yaml)

zfs snapshot data/datasets@pre-run-2026-05-14
zfs rollback data/datasets@pre-run-2026-05-14

ashift=12 = 4 KiB-blokke — hvis du gør dette forkert ved oprettelsen af ​​puljen, kan du ikke rette det uden at ødelægge puljen. recordsize=1M til arbejdsbelastninger med store filer (standard 128 KiB er for lille til shards på flere GB). xattr=sa gemmer xattrs inline, massivt hurtigere end standarden.

Btrfs — undgås generelt til produktions-AI

Btrfs har de samme konceptuelle funktioner som ZFS — COW, snapshots, checksums, indbygget RAID. På papiret, ikke sandt; i praksis anbefaler vi det ikke på Kentino-servere. RAID5/6 har kendte datatabsfejl, som projektet selv markerer som ikke produktionsklar (RAID1/10 er stabile, paritetstilstande er ikke); ydeevnen forringes kraftigt under det fragmenteringsmønster, som AI-arbejdsbelastninger producerer (gradient checkpoints, caches); snapshot-ydeevnen falder drastisk over et par hundrede snapshots, som en arbejdsgang pr. eksperiment rammer inden for et kvartal; og værktøjerne er mindre modne end ZFS eller XFS til replikering, overvågning og scrub-planlægning. Fint på en bærbar computer. For en multi-GPU-server med snesevis af TB træningsdata, vælg XFS eller ZFS.

RAID-layouts — hvad skal filsystemet parres med

RAID-niveau Brug sag Redundans Noter
RAID0 Scratch (flygtig, regenererbar) Ingen Kun for data, du kan genopbygge
RAID10 Træningsdatasæt, kontrolpunkter 1 pr. spejl Bedste hastighed + sikkerhed til hot data
RAID-Z1 / RAID5 Undgå ved nybyggeri 1 disk Genopbygningstider på 16 TB+ drev gør Z1 risikabelt
RAID-Z2 / RAID6 Arkiv, kold datalagring 2 diske Det rigtige valg til store mængder
RAID-Z3 Brede arrays (12+ diske) 3 diske Kun når arraybredden tvinger det

På drev på 16 TB+ kan en genopbygning af en enkelt disk tage 24-72 timer, og en anden fejl på tværs af drev med samme batch i det vindue er ikke ubetydelig. Enkeltparitet er ikke længere den sikre standard. Brug Z2/RAID6 eller filspejle.

Små filer versus store filer

Spørgsmålet, der fanger folk mere end noget andet filsystemvalg: hvordan opfører dit filsystem sig med 50 millioner 4 KB-billeder i et mappetræ? ​​Svaret for alle filsystemer her: dårligt.

Metadata pr. fil (inode, dentry, timestamps, xattrs) kører 200-500 bytes uanset filstørrelse — 50 millioner små filer brænder 10-25 GB metadata, før de lagrer en byte pixeldata. Åbn/læs/luk-mønsteret binder metadatasiden og blokerer DataLoader-workers.

Løsningen er ikke filsystemet. Gem ikke små filer som filer. Pak ind i webdataset / tar / parquet / lmdb / hdf5 / safetensors og stream sekventielt — PyTorch's WebDataset og NVIDIA DALI forventer begge dette. Filsystemet ser derefter et lille antal store filer, hvilket alle filsystemer her er gode til. Hvis du skal holde individuelle filer i stor skala, ZFS med recordsize=16k og xattr=sa er den mindst dårlige løsning, men den virkelige løsning er at pakke om.

Direkte I/O, sidecache og O_DIRECT

PyTorch bruger Linux-sidecachen til gentagne datasæt-epoker — epoke 1 fra disk, epoker 2..N fra RAM. Nogle arbejdsbelastninger bruger O_DIRECT at omgå cachen ved store læsninger, hvor data kun berøres én gang. NVIDIAs GPUDirect-lagring går endnu videre og bruger DMA'er til at NVMe → GPU direkte.

ext4 og XFS ære O_DIRECT korrekt — justeret direkte I/O, ingen sidecache. ZFS ignorerer O_DIRECT (al I/O via ARC, per design): fint til de fleste arbejdsbelastninger, en hård inkompatibilitet med GPUDirect Storage. Justering er vigtig — buffer og offset skal justeres til enhedens blokstørrelse (typisk 4 KB).

Hvis du planlægger at bruge GPUDirect Storage til at forsyne en 8-GPU-boks med fuld båndbredde, /data skal være XFS på NVMe. Hvis du ikke ved, hvad GPUDirect Storage er, og træning er computerbundet, har du ikke brug for det endnu.

NVMe-multipath

Dual-port U.2 / E1.S NVMe præsenteres som to PCIe-stier hver. Linux NVMe-driveren bruger native multipath (nvme_core.multipath=Y, standard i moderne kerner), hvilket giver failover og round-robin load balancing. Usynlig på filsystemlaget, men den har betydning for failover (uden den får en sti-/HBA-fejl drevet til at forsvinde, og filsystemet går i panik) og båndbredde (et U.2-drev med flere stier når ~14 GB/s versus 7 GB/s med én sti).

cat /sys/module/nvme_core/parameters/multipath   # expect: Y
nvme list-subsys

For forbruger M.2 NVMe (5090 desktop-klasse builds) er multipath ikke relevant – én sti. For 8-GPU EPYC builds med Enterprise U.2 / E1.S i et backplane med to controllere, skal den lades være aktiveret.

Overhead for checksum

Produktion CPU-pris pr. GB, én kerne Noter
ZFS fletcher4 (standard) ~50–100 ms Standard datablok checksum
ZFS lz4 komprimering ~150–250 ms Betaler sig normalt tilbage via reduceret I/O
ZFS zstd komprimering ~400–800 ms Bedre forhold, højere omkostninger
XFS / ext4 (ingen datakontrolsum) 0 Kun metadata

På en 64-core EPYC-vært er omkostningerne usynlige. På en 16-core Xeon under vedvarende belastning kan ZFS stjæle 5-10% af den effektive CPU - om det betyder noget afhænger af, om træningen er CPU-bundet til forbehandling (ofte ja for vision) eller GPU-bundet (ofte ja for store LLM'er).

Den ærlige fremstilling: ZFS fanger bitrot, som du ellers aldrig ville bemærke, før din model træner på subtilt korrupte data. For et datasæt, du har brugt seks måneder på at opbygge, er 5-10% det værd. For ephemer scratch, som du regenererer ugentligt, er det ikke tilfældet.

NFS til delte datasæt på tværs af klyngenoder

Når du har mere end én server, bliver det interessant, hvor datasættet befinder sig. Tre mønstre:

  1. Kopiér til hver node. Simpelt, spilder kapacitet. Kan bruges til <1 TB og ≤4 noder.
  2. NFS fra en dedikeret lagringsserver. Én kanonisk kopi. Netværket er flaskehalsen — minimum 25 GbE, 100 GbE til træning med flere noder.
  3. Parallelt filsystem (BeeGFS, Lustre, WekaFS). Større løft, skalerer forbi hvor NFS falder over.

For 1-4 noder er NFS korrekt. Server: XFS på RAID10 NVMe, eksporteret via NFSv4. Klient: monter med nconnect=8 at parallelisere på tværs af TCP-forbindelser.

# Server /etc/exports
/data/shared 10.0.10.0/24(rw,async,no_subtree_check,no_root_squash)

# Client
mount -t nfs -o vers=4.2,nconnect=8,proto=tcp,rsize=1048576,wsize=1048576 \
  storage01:/data/shared /mnt/shared

NFS over 100 GbE med nconnect=8 leverer 8-10 GB/s vedvarende — nok til 16 GPU'er på typisk vision- eller LLM-træning. Udover det, BeeGFS / Lustre — en anden artikel.

Komplet eksempel: 8-GPU EPYC, 24 NVMe + 8 SAS

2× 480 GB NVMe  (boot)     → md RAID1   → ext4 → /
8× 7.68 TB NVMe (scratch)  → md RAID0   → XFS  → /scratch
8× 7.68 TB NVMe (data)     → md RAID10  → XFS  → /data
8× 16 TB SAS    (archive)  → 2× RAID-Z2 → ZFS  → /archive

ZFS ARC: 64 GB of 512 GB RAM. NVMe multipath: on. NFS export: /data over 100 GbE.
mkfs.ext4 -L root /dev/md0
mkfs.xfs -f -d su=64k,sw=8 -l size=512m -L scratch /dev/md1
mkfs.xfs -f -d su=64k,sw=4 -l size=512m -L data    /dev/md2

zpool create -o ashift=12 \
  -O compression=zstd -O atime=off -O xattr=sa -O recordsize=1M \
  archive raidz2 /dev/sd[a-h]

echo "options zfs zfs_arc_max=68719476736" > /etc/modprobe.d/zfs.conf
update-initramfs -u

Rå NVMe-gennemstrømning, hvor du har brug for det, redundans, hvor dataene er uerstattelige, komprimeret checksum-bulk til alt andet.

Hvad skal jeg gøre næste

Før du formaterer noget, skal du svare på:

  1. Største datasæt, i TB? Størrelser /data og fortæller dig, om du har brug for et arkivniveau.
  2. Kan træningsdata regenereres fra en sandhedskilde? Hvis ja, er RAID0 fra bunden fint. Hvis nej, RAID10 minimum, overvej ZFS på /data.
  3. Hvor mange GPU'er læser den samme mængde samtidigt? Over ~8 parallelle DataLoader-processer betaler XFS's allokeringsgrupper tilbage i forhold til ext4.
  4. Har du brug for øjebliksbilleder? "Fork et datasæt og rul tilbage" → ZFS. Ellers er XFS hurtigere og enklere.
  5. RAM-budget, og hvor meget kan ZFS klare? Beslut dig før installation, ikke efter den første OOM.

Valg af filsystem er ikke den mest interessante beslutning, man træffer om en AI-server, men det er en af ​​de få, der virkelig er svære at omgøre. Vælg bevidst, formater én gang, og kom videre.


Dette er en del af Kentino Wiki, en referenceserie om AI-beregning, lagring og de systemer, der forbinder dem. Kommentarer og rettelser er velkomne på info@kentino.com.