Nell’ultimo periodo sto studiando molto i modelli IA ed il training, e per farlo utilizzo WSL2 su Windows. Per il test dei modelli, però, uso a volte Windows 11 nativo, anche se provo ad evitarne il più possibile l’utilizzo… e questa situazione porta 2 conseguenze da tenere costantemente sotto controllo:
- Windows limita l’espansione del disco virtuale su cui risiede WSL2, ed il download dei modelli, unitamente al download delle dipendenze Python necessarie per il loro utilizzo, satura velocemente questo spazio;
- Se si usano tool su Windows che sfruttano gli stessi modelli usati su WSL2, quelli già scaricati, che risiedono sulla partizione virtuale destinata a Linux non vengono automaticamente visti e quindi finiscono per occupare il doppio dello spazio;
- In ogni caso, accedere da Windows alla partizione WSL2, ed al contrario da WSL2 alla partizione Windows comporta un drastico crollo delle performance di I/O dovute al passaggio attraverso il layer 9P.
Occorre quindi trovare una soluzione a questo problema, ma, spoiler alert, non esiste senza compromessi.
La valutazione delle soluzioni
Per poter trovare una soluzione sono ovviamente partito dall’obiettivo e dalle varie possibilità per raggiungerlo. L’obiettivo è quello di poter accedere alla medesima directory, sia da Windows che da WSL2, alla medesima velocità data dal massimo dello sfruttamento della tecnologia su cui risiede (es. per NVME M.2 su PCiE 4.0 sarebbe 7.876,8 MB/s). Il compromesso, qualsiasi, pur di sfruttare la directory dei modelli su WSL2 al 100%, pur compromettendo il minimo possibile la lettura e la scrittura su quella directory da parte di Windows… questo perché uso principalmente i modelli IA su WSL2.
Tornare a WSL1?
Sembrerà folle ma ha comunque un senso… qualche utente su Reddit infatti consigliava di fare un rollback a WSL1 per risolvere il problema dello spazio condiviso Windows – Linux per ospitare i modelli, e questo perché WSL1 utilizza un layer di traduzione syscall anziché una macchina virtuale completa, una caratteristica che elimina completamente il problema del filesystem. Infatti accedendo a /mnt/c/ si ottiengono prestazioni quasi native perché non c’è il layer 9P di virtualizzazione, il che si traduce con un dataset da 300GB su NTFS che verrebbe letto a velocità native del disco (2-3 GB/s su NVMe) senza penalità significative. Inoltre, WSL1 ha un overhead di memoria drasticamente inferiore (non riserva RAM per una VM) e l’accesso ai file tra Windows e Linux è bidirezionale e istantaneo senza bisogno di network share o conversioni. Per workload puramente I/O-bound su filesystem Windows, WSL1 può risultare più veloce di WSL2.
Tuttavia il problema fondamentale è che WSL1 non ha un kernel Linux reale e mancano funzionalità kernel essenziali come il supporto completo a CUDA, driver GPU proprietari nativi, e syscall avanzate richieste da framework di deep learning. PyTorch e TensorFlow utilizzano chiamate kernel (come ioctl per GPU, memfd_create, scheduler real-time) che WSL1 traduce in modo imperfetto o non supporta affatto, causando crash, errori silenziosi o performance GPU drasticamente ridotte. Inoltre non ha accesso a tecnologie come Docker containers nativi, networking avanzato (necessario per training distribuito), e molti tool di profiling GPU semplicemente non funzionano. A conti fatti WSL1 risolve il problema I/O ma rende impossibile sfruttare la GPU per il training, vanificando completamente l’obiettivo.
Verdetto
Inutilizzabile
Dataset su Disco Windows
Utilizzare direttamente la partizione NTFS di Windows (quella già montata automaticamente in /mnt/c/ o /mnt/d/) rappresenta il compromesso più semplice da implementare perché non richiede configurazioni aggiuntive, partizionamenti complessi, o l’uso di filesystem alternativi per Windows. NTFS è universalmente supportato, ogni tool Windows può accedervi nativamente con performance massime (3+ GB/s su NVMe moderni), e la compatibilità è garantita al 100% con qualsiasi software, backup tool, o utility di sistema. A differenza di ext4, non c’è bisogno di driver di terze parti, preoccupazioni su permessi POSIX mal tradotti, o rischi di corruzione se Windows e WSL2 accedono simultaneamente ai file. Per chi ha già i dati su Windows e vuole evitare pesanti migrazioni, questa soluzione elimina completamente il data shifting del dataset da 300GB.
Il problema emerge invece quando WSL2 accede a /mnt/c/: Microsoft utilizza il protocollo 9P attraverso il layer di virtualizzazione Hyper-V per esporre i filesystem Windows a Linux, e questo significa che ogni operazione I/O deve attraversare il boundary VM→Host→VM, con serializzazione dei metadati, conversione tra semantica filesystem Windows e Linux, e latency di network virtuale. Nei benchmark reali, accedere a NTFS via /mnt/c/ in WSL2 raggiunge appena 300-400 MB/s in lettura su NVMe (contro i 3.2 GB/s di ext4 nativo), con overhead ancora più marcato su operazioni random tipiche del data loading per training IA (accesso a migliaia di immagini piccole). Il layer 9P diventa un bottleneck invalicabile: non importa quanto sia veloce l’NVMe, WSL2 non può superare queste limitazioni architetturali quando accede a filesystem Windows.
Si tratta tuttavia di una soluzione accettabile se il workflow è prevalentemente basato su Windows (80% del tempo si usano tool nativi Windows, si fa invece training occasionale su WSL2) e si vuole massimizzare la semplicità. Per training intensivo dove WSL2 è l’ambiente primario, come nel mio caso, questa soluzione va a sacrificare l’80-90% delle performance I/O potenziali: la GPU potrebbe rimanere sottoutilizzata in attesa che il dataloader fornisca i batch attraverso il lento tunnel 9P, e questo potrebbe essere accettabile per test e sviluppo ma sicuramente inadeguato per production training su dataset enormi con GPU moderne.
Verdetto
R/W da Windows 11: 10/10 (nativo NTFS)
R/W da WSL2: 4/10 (layer 9P, ~300-400 MB/s)
Dataset su Disco WSL2
Lasciare il dataset su WSL2 è l’approccio “zero sbatti” più immediato per chi come me lavora principalmente sull’ambiente Linux, e devo ammettere che è il sistema che ho utilizzato fino ad ora. WSL2 utilizza un file VHDX (ext4.vhdx) che contiene un filesystem ext4 completo, e quando si accede ai file dall’interno di WSL2 si ottengono performance native perché il kernel Linux legge direttamente ext4 senza alcun layer di traduzione, raggiungendo facilmente più di 3 GB/s in lettura sequenziale su NVMe moderni, e per il training di modelli IA questo è l’ideale: il dataloader può saturare completamente la GPU senza bottleneck I/O, le operazioni su milioni di file piccoli (immagini, checkpoint) sono gestite in modo ottimale dal filesystem ext4, e non ci si deve preoccupare di mount point, configurazioni complesse, o compatibilità perché tutto funziona esattamente come su una distribuzione Linux nativa.
Il problema emerge invece quando si vuole accedere a quei dati da Windows: l’unico modo è attraverso il network share \\wsl$\Ubuntu\home\user\, che utilizza esattamente lo stesso protocollo 9P che penalizza l’accesso a /mnt/c/, ma al contrario (Windows→WSL2 invece di WSL2→Windows). Le performance crollano a 300-400 MB/s per operazioni che su disco nativo farebbero 3 GB/s e copiare un modello da 50GB diventa un’operazione estremamente più lunga, navigare cartelle con migliaia di immagini in Explorer diventa molto lento, e qualsiasi tool Windows che debba processare il dataset (backup, analisi, conversione) sarà drammaticamente rallentato, vi lascio solo immaginare come possa girare su Windows un tool che sfrutta un modello IA che risiede su WSL2…
Questa soluzione, tuttavia, è perfetta per chi ha il 90% del proprio workflow su WSL2, con training continuo, preprocessing con script Python, gestione modelli via CLI Linux e l’accesso occasionale da Windows è accettabilmente lento ma non bloccante. Si rivela quindi la scelta giusta per chi considera Windows semplicemente come “l’host che fa girare WSL2” e si serve principalmente del terminale Linux. Il vantaggio enorme è che è tutto già pronto con l’installazione di WSL2.
Altro aspetto da menzionare è che il VHDX di WSL2 cresce automaticamente, come anticipato, fino al massimo predefinito (spesso 256GB o 512GB, configurabile). Se il dataset supera questi limiti bisogna espandere manualmente il VHDX tramite comandi PowerShell, una procedura, per quanto semplice, non automatica. Inoltre, WSL2 non rilascia automaticamente spazio quando si cancellano file dal disco ed il VHDX rimane alla dimensione massima raggiunta finché non si compatta manualmente con wsl --manage --set-sparse. Questo è uno dei problemi più rilevanti per chi opta per questa soluzione perché se lo spazio sul disco host finisce non basta liberare spazio sul disco Linux. Inoltre ritengo che si crea troppa confusione tra spazio occupato dai modelli, spazio occupato dai progetti e dai tool, e spazio occupato dalla cache di pip, è molto più comodo avere un disco (o una parte di esso) destinata solo ai modelli, in modo da avere un quadro di insieme subito disponibile, è finito lo spazio sul disco dei modelli? faccio pulizia di modelli.
R/W da Windows 11: 4/10 (layer 9P, ~300-400 MB/s)
R/W da WSL2: 10/10 (Performance native Ext4)
Dev Drive ReFS
Dev Drive è una funzionalità introdotta in Windows 11 22H2 specificamente pensata per sviluppatori: utilizza il filesystem ReFS (Resilient File System) con ottimizzazioni dedicate per gestire milioni di file piccoli (tipici di progetti software e dataset IA), offre Copy-on-Write efficiente per snapshots istantanei, e viene automaticamente escluso da Windows Defender per ridurre l’overhead durante operazioni I/O intensive. Microsoft lo pubblicizza come la soluzione ideale per workload development-heavy, con performance native eccellenti su Windows (facilmente 2-3 GB/s su NVMe) e resilienza superiore a NTFS contro corruzione dei dati. Per chi lavora esclusivamente su Windows con Visual Studio, Node.js, o compilation di progetti enormi, Dev Drive è effettivamente un’ottima scelta. Tuttavia, WSL2 non può sfruttare questi vantaggi: qualsiasi filesystem Windows (NTFS, ReFS, Dev Drive) viene utilizzato attraverso il protocollo 9P tramite il layer di virtualizzazione Hyper-V. Questo significa che anche se il Dev Drive raggiunge 3 GB/s nativamente su Windows, quando WSL2 accede a /mnt/d/ (dove è montato il Dev Drive), le performance crollano a 300-400 MB/s esattamente come con NTFS tradizionale. Anche in questo caso il layer 9P introduce latenza significativa per ogni syscall, serializzazione dei metadati, e conversione continua tra semantica filesystem Windows e Linux. Nei benchmark reali, Dev Drive su WSL2 si comporta in maniera identica a /mnt/c/ standard, il training di modelli IA rimane limitato dalla velocità del network share virtuale, rendendo la GPU sottoutilizzata durante il data loading. ReFS non risolve il bottleneck architetturale di WSL2, ma l’assenza di Windows Defender su Dev Drive migliora la costanza delle operazioni I/O lato Windows.
Verdetto
R/W da Windows 11: 10/10 (Performance native NVMe, ottimizzazioni ReFS attive con vantaggio in termini di overhead di Defender)
R/W da WSL2: 5/10 (Limitato dal layer 9P, ~300-400 MB/s indipendentemente da ReFS)
VHDX ext4 Fisso
Creare un file VHDX (Virtual Hard Disk) formattato con ext4 e montarlo permanentemente in WSL2 rappresenta un valido compromesso tra performance e flessibilità. A differenza delle partizioni fisiche, un VHDX è semplicemente un file che risiede su Windows (ad esempio D:\WSL\training.vhdx) ma contiene al suo interno un filesystem ext4 completo. WSL2 può montare questo VHDX e accedervi con performance quasi native perché il kernel Linux legge direttamente il filesystem ext4 senza passare attraverso il layer 9P: ci si aspettano circa 2.8-3 GB/s in lettura (contro i 3.2 GB/s di una partizione ext4 fisica pura), con un overhead minimo dovuto solo alla gestione del container VHDX. Il vantaggio enorme è la portabilità: è possibile spostare il file VHDX su altri dischi, farne backup completi, o trasferirlo su altre macchine mantenendo intatto l’intero ambiente di training. Ma il vero vantaggio di questa soluzione è che Windows può montare direttamente il VHDX quando WSL2 non lo sta usando: con driver ext4 di terze parti (come WSL2-Linux-Kernel integrato o ext2fsd) è possibile esporre il contenuto del VHDX come drive Windows e accedervi con performance vicine al nativo (~2 GB/s), permettendo la gestione dei dataset con Explorer, fare analisi con tool Windows, o copiare file senza passare per il lento \\wsl$\. Il limite è che l’accesso non può essere simultaneo: è necessario smontare il VHDX da WSL2 prima di montarlo su Windows (e viceversa), altrimenti si rischia la corruzione del filesystem. Questo workflow richiede un minimo di organizzazione ma è perfettamente gestibile.
La creazione è semplice: wsl --mount --vhd D:\WSL\training.vhdx --bare, su formatta con ext4, e si configura WSL2 per montarlo automaticamente all’avvio ad esempio tramite /etc/wsl.conf. A differenza di una partizione fisica, se il dataset cresce oltre i 300GB iniziali, si può espandere il VHDX dinamicamente con comandi PowerShell senza riformattare. L’unico aspetto da considerare è lo spazio: il VHDX occupa fisicamente su NTFS lo spazio che effettivamente si utilizza (con 200GB di dati, il file sarà ~200GB), ma bisogna pre-allocare la dimensione massima per evitare frammentazione e garantire performance costanti. Per dataset IA enormi, questa soluzione offre il miglior bilanciamento tra velocità WSL2, accesso occasionale Windows, e semplicità operativa.
Verdetto
R/W da Windows 11: 7/10 (quasi nativo se montato direttamente, ma non simultaneo e richiede gestione manuale)
R/W da WSL2: 9/10 (ext4 quasi nativo, ~2.8–3 GB/s, overhead minimo VHDX)
Conclusioni
Anche se all’apparenza la soluzione VHDX ext4 Fisso sembra la più equilibrata, nel mio caso non lo è, questo perché utilizzo i modelli su Windows davvero sporadicamente e preferisco sicuramente le massime performance su WSL2 seppur a discapito di quelle su Windows. Anche la soluzione Dataset su Disco WSL2 potrebbe essere valida, ma preferisco comunque avere un riscontro immediato quando i modelli esauriscono lo spazio e comunque il fatto di dover ottimizzare lo spazio del disco WSL2 a seguito della pulizia dei modelli lo rende un passaggio in più. Infine avere i modelli su un disco che non sia virtuale ad espansione dinamica comunque evita un piccolo overhead che altrimenti si verifica con il disco principale di WSL2.
Per risolvere questi limiti, ho aggiunto un NVMe secondario: 60 GB sono dedicati a Ubuntu nativo, per lavorare direttamente sull’ambiente Linux completo quando serve, mentre il resto del disco ospita una partizione BTRFS per i dati condivisi tra Ubuntu, WSL2 e Windows. Su Windows generalmente mi limito a leggere i dati, quindi il driver Linux File Systems for Windows di Paragon è sufficiente. Se fosse necessario scrivere da Windows, la soluzione alternativa sarebbe usare ext4 al posto di BTRFS tramite Paragon.
BTRFS è stato scelto per le sue funzionalità avanzate rispetto a ext4: snapshot, checksum e gestione dei metadati, molto utili su dataset grandi e condivisi tra sistemi diversi. In questo modo riesco a combinare massime performance su WSL2, accesso rapido e sicuro da Windows e Ubuntu nativo, e una gestione dei dataset chiara e trasparente, senza colli di bottiglia I/O o procedure operative complicate.

Lascia un commento