DGX & Cluster Storage
Everything storage on a DGX cluster: the storage hierarchy, NVMe and nvme-cli, RAID levels and why /raid is RAID 0, mdadm, local caching (FS-Cache, staging, container caches), shared and parallel filesystems, GPUDirect Storage, tuning and benchmarking with fio, data loading and checkpointing. Part B covers changing node storage layouts the BCM way.
1. The storage hierarchy for AI
A training job reads data that starts far away (shared storage) and must end up in GPU memory. Each tier is faster and smaller than the one below it:
| Tier | Example on DGX H100 | Rough scale | Role |
|---|---|---|---|
| GPU memory (HBM3) | 80 GB per GPU, 640 GB per node | ~3 TB/s per GPU | Model weights, activations, the current batch |
| Host memory (DRAM) | 2 TB | Hundreds of GB/s | Linux page cache, data-loader buffers, pinned staging |
Local NVMe (/raid) | 8 × 3.84 TB in RAID 0 ≈ 30 TB | Tens of GB/s aggregate | Node-local cache / scratch: staged datasets, NFS cache, container images |
| Shared high-performance storage | Parallel filesystem over the storage network | PB scale, high aggregate bandwidth across nodes | The source of truth for datasets and checkpoints |
| Capacity / archive | NFS filers, object storage (S3), tape | Cheapest per TB | Raw data lakes, long-term retention, home directories |
/raid is the stockroom at the back of the shop, DRAM is the shelf behind the counter, and HBM is what's in the cashier's hands. If the stockroom burns down you restock from the warehouse; you never keep the only copy of anything in the stockroom.1b. Where each file lives, and which network it crosses
Knowing the tiers isn't enough: questions describe a specific file (a container image, a checkpoint, a home directory) and ask where it belongs or why something is slow. This map covers the usual artifacts on a DGX cluster. Paths are typical examples; sites name their mounts differently.
| Artifact | Typical path | Lives on | Type | Reached over | Why there |
|---|---|---|---|---|---|
| OS, kernel, drivers (GPU driver, DOCA/OFED, Fabric Manager) | /, /boot, /usr/lib/modules | Local OS mirror (2 × M.2 NVMe, RAID 1). Not /raid. | Block (local filesystem) | Written by BCM at provisioning over in-band | The node must boot and run with shared storage down. The master copy is the BCM software image. |
| BCM software images, PXE boot files | /cm/images/<image> on the head node | Head node disk (kept in sync with the passive head node in an HA pair) | Local filesystem on the head node | Served to nodes over in-band (PXE, then the node installer syncs the image) | One central definition of every node's OS (Part B) |
| Cluster-wide software | /cm/shared (BCM), modules, tools | NFS export from the head node or a NAS | Shared file (NFS) | In-band | Install once, visible on every node |
| Container images | Enroot cache/data on /raid (ENROOT_CACHE_PATH, ENROOT_DATA_PATH); Docker data-root on /raid; or prebuilt .sqsh files on shared storage | Local /raid cache, or a shared copy | Local file / shared file | Pulled from nvcr.io north-south over in-band once; a shared .sqsh comes over the storage or in-band network | A 15–30 GB NGC image pulled once per node, not per job (NGC guide) |
| Node logs | /var/log, the systemd journal, dmesg | Local OS drive, forwarded to the head node or monitoring stack | Block (local filesystem) | Forwarding over in-band. The BMC's own event log (SEL) is read over OOB. | Readable locally even when the network is the problem |
| Home directories, code, configs | /home/<user> | NFS user storage | Shared file (NFS) | In-band (not the storage fabric) | Same scripts and .bashrc on every node; small, backed up. Not for datasets or checkpoints. |
| Active training datasets | /lustre/datasets/… (master), staged to /raid/data/… | Parallel filesystem (high-performance storage); repeated reads from the local cache | Shared file (parallel FS) | Storage fabric; from /raid it's local PCIe | Aggregate bandwidth from many storage servers; local NVMe absorbs epoch after epoch |
| Checkpoints | /lustre/<project>/checkpoints/ | Parallel filesystem | Shared file (parallel FS) | Storage fabric | Must survive node loss; every rank writes its shard in parallel |
| Model weights for fine-tuning or inference | Master in object storage, NGC, or the parallel FS; cached at /raid/models or a NIM cache (NIM_CACHE_PATH) | Master copy shared, working copy cached locally | Object or shared file, then local file | Storage fabric or in-band (north-south) once, then local | See loading model weights |
| Job scratch | /raid/tmp/$SLURM_JOB_ID | Local /raid | Local file | None (local) | Fast and disposable; cleaned in the Slurm epilog |
| Raw data lake, archives, old checkpoints | s3://ai-data-lake/raw-2026/ | Object storage (S3-compatible) | Object | Usually north-south over in-band, or the storage Ethernet where the design shares it | Cheap and durable for immutable data; subsets are staged into the parallel FS for training |
Block, file, and object: what the "type" column means
| Type | How it's used | On a DGX cluster |
|---|---|---|
| Block | A raw disk (or LUN) that one host owns; the host puts its own filesystem on it | The OS mirror and /raid. Not shared between nodes. |
| File | A shared directory tree with POSIX semantics (open, seek, rename, permissions) mounted by many hosts | NFS for homes and software; Lustre, WEKA, Storage Scale, VAST for datasets and checkpoints |
| Object | Whole objects in buckets, addressed by key over an HTTP API (S3). No in-place edits or POSIX mounts by default. | Data lake, archives, model registries. Staged or streamed, not used as a working directory. |
Which network, step by step: one training job
| # | Step | What moves | Network |
|---|---|---|---|
| 1 | Node boots | PXE boot, software image sync from the head node | In-band |
| 2 | Job submitted and started | Slurm control traffic | In-band |
| 3 | Container ready | Image pulled from nvcr.io to /raid (first time), or a shared .sqsh read | In-band (north-south), or storage |
| 4 | Code and configs read | Scripts from $HOME | In-band (NFS) |
| 5 | Data staged | Dataset shards from the parallel FS to /raid (prolog or first step) | Storage fabric |
| 6 | Weights loaded | Each GPU's shard of the starting model or checkpoint | Storage fabric, or local NVMe if cached |
| 7 | Every training step | Batches from /raid or the parallel FS into GPU memory (GDS can skip CPU memory); gradients exchanged between GPUs | Local PCIe / storage fabric for data; NVLink inside the node and the compute fabric between nodes for gradients |
| 8 | Checkpoint | Model and optimizer state, sharded by rank | Storage fabric |
| 9 | Monitoring | Logs, DCGM metrics, job output | In-band |
| 10 | A node hangs | Power cycle and console through the BMC | Out-of-band |
| 11 | Run finished | Final model exported to object storage or a registry | In-band (north-south) or storage |
2. Disk basics: disks, partitions, filesystems
| Concept | What it is | Example |
|---|---|---|
| Disk (SSD / NVMe) | The physical storage device. | /dev/nvme0n1 |
| Partition | A slice of the disk set aside for a purpose. The partition table (GPT) records where each slice starts and ends. | /dev/nvme0n1p2 = 100 GB for the OS |
| Filesystem | The structure written inside a partition so it can store files (ext4, xfs). | ext4 on the OS partition |
| Mount point | Where the filesystem appears in the directory tree. | /, /boot/efi, /raid |
| RAID | Combines several disks into one logical device for speed, redundancy, or both. | /dev/md0 (OS mirror), /dev/md1 (data stripe) |
$ lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
nvme0n1 1.7T disk
├─nvme0n1p1 512M part vfat /boot/efi
└─nvme0n1p2 1.7T part linux_raid_member
└─md0 1.7T raid1 ext4 /
nvme1n1 1.7T disk (mirror of nvme0n1)
nvme2n1 3.5T disk linux_raid_member
└─md1 27.9T raid0 ext4 /raid
... nvme3n1 – nvme9n1 (the other 7 data drives, also in md1)
md0/md1, nvme numbering) and filesystem types vary by DGX model and OS release. Use lsblk and cat /proc/mdstat on the actual system.3. NVMe fundamentals
| Concept | Meaning |
|---|---|
| NVMe (Non-Volatile Memory Express) | A storage protocol designed for flash over PCIe. It replaced SATA/SAS (designed for spinning disks). |
| Queues | Up to 64K I/O queues, each up to 64K commands deep, one or more per CPU core. That parallelism is why NVMe is so fast. |
| PCIe lanes | A typical drive uses x4. Roughly ~8 GB/s for Gen4 x4 and ~16 GB/s for Gen5 x4 theoretical. |
| Namespace | A logical "disk" exposed by the controller (nvme0n1 = controller 0, namespace 1). Drives can be split into several namespaces. |
| Form factors | M.2 (small stick: DGX boot/OS drives), U.2 (2.5" hot-swap: DGX data drives), E1.S / E3.S (newer data-centre form factors) |
| Endurance | Flash wears out. Rated as DWPD (drive writes per day over the warranty) or TBW (total terabytes written). |
| NVMe-oF | NVMe over Fabrics: NVMe commands over RDMA (IB/RoCE) or TCP, so remote flash looks almost local |
cp or dd barely scratches it. Benchmarks and data loaders need multiple workers and queue depth to see the real numbers.4. nvme-cli: inventory, health, and erase
sudo nvme list # all NVMe devices: model, serial, size, firmware
sudo nvme smart-log /dev/nvme2 # health
# critical_warning : 0 <- non-zero = act now
# temperature : 38 C
# available_spare : 100%
# percentage_used : 3% <- endurance consumed (can exceed 100%)
# data_units_written : ...
# media_errors : 0 <- should stay 0
# num_err_log_entries : 0
# unsafe_shutdowns : 4
sudo nvme error-log /dev/nvme2
sudo nvme id-ctrl /dev/nvme2 | grep -E 'mn|fr' # model, firmware revision
sudo nvme fw-log /dev/nvme2
# Erasing (DESTROYS DATA)
sudo nvme format /dev/nvme2n1 --ses=1 # secure erase user data
sudo nvme sanitize /dev/nvme2 -a 2 # block-erase sanitize (drive-wide)
| SMART field | Watch for |
|---|---|
critical_warning | Any non-zero bit (spare low, temperature, reliability degraded, read-only mode) |
percentage_used | Endurance consumed. Plan replacement as it approaches 100%. |
media_errors | Unrecovered data errors. Rising = replace the drive. |
available_spare | Remaining spare blocks. Dropping toward the threshold = failing. |
nvsm show health and nvsm show storage summarize drive and RAID health, and nvsm dump health collects it for support. See NVSM mastery.5. RAID levels
| Level | How it works | Usable capacity (n disks) | Survives | Performance | Typical use |
|---|---|---|---|---|---|
| RAID 0 (stripe) | Data split in chunks across all disks | 100% (n × size) | 0 failures: any disk lost = all data lost | Best: reads and writes scale with n, no parity cost | Scratch / cache (DGX /raid) |
| RAID 1 (mirror) | Identical copy on each disk | 1 disk's worth (50% with 2) | n − 1 failures | Reads can use both; writes go to all | OS / boot (DGX OS drives) |
| RAID 5 | Striping + 1 distributed parity block | (n − 1) × size | 1 failure | Good reads; writes pay a parity penalty (read-modify-write, about 4 I/Os per small write) | General file servers |
| RAID 6 | Striping + 2 parity blocks | (n − 2) × size | 2 failures | Bigger write penalty (about 6 I/Os) | Large-capacity arrays where rebuilds take long |
| RAID 10 | Mirrored pairs, striped together | 50% | 1 per mirror pair (at least 1) | Fast reads and writes, no parity | Databases, write-heavy important data |
6. RAID calculator
fio.7. Software RAID with mdadm
DGX systems use Linux software RAID (md, managed with mdadm) rather than a hardware RAID card. NVMe drives are fast enough that a RAID controller would be a bottleneck, and software RAID is flexible and transparent.
cat /proc/mdstat # all md arrays and their state
# md1 : active raid0 nvme9n1[7] nvme8n1[6] ... nvme2n1[0]
# md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
# [UU] <- both mirror halves Up; [U_] = degraded
sudo mdadm --detail /dev/md0 # state, members, failed/spare devices
sudo mdadm --examine /dev/nvme0n1p2 # RAID metadata on one member
# RAID 1: replace a failed mirror member
sudo mdadm /dev/md0 --fail /dev/nvme1n1p2 --remove /dev/nvme1n1p2
# (swap the drive, partition it like the other one, then)
sudo mdadm /dev/md0 --add /dev/nvme1n1p2 # rebuild starts; watch /proc/mdstat
# RAID 0: there's nothing to rebuild. A lost member means re-creating the array:
sudo mdadm --create /dev/md1 --level=0 --raid-devices=8 /dev/nvme{2..9}n1
sudo mkfs.ext4 /dev/md1 # then mount at /raid and refill the cache
configure_raid_array.py) and documents the exact steps to recreate and remount /raid after a drive replacement. Use the documented procedure for your DGX model rather than raw mdadm where one exists.8. How storage is laid out on DGX systems
| System | OS drives | Data / cache drives |
|---|---|---|
| DGX H100 / H200 | 2 × 1.92 TB M.2 NVMe, RAID 1 | 8 × 3.84 TB U.2 NVMe, RAID 0 at /raid (~30 TB) |
| DGX A100 | 2 × 1.92 TB M.2 NVMe, RAID 1 | 4 × 3.84 TB U.2 (~15 TB) standard, or 8 (~30 TB) on the larger configuration, RAID 0 |
| DGX B200 | 2 × ~1.9 TB M.2 NVMe, RAID 1 | 8 × 3.84 TB U.2 NVMe, RAID 0 (~30 TB) |
| Storage | Purpose | If it fails |
|---|---|---|
| OS RAID 1 | DGX OS / BCM-provisioned OS | One drive can fail with no outage; replace it and rebuild |
/raid RAID 0 | Fast local cache and scratch: datasets, NFS cache, container images, temporary job files | Any one drive lost = the whole array is lost. Recreate it and repopulate from shared storage. |
| Shared storage (over the storage network) | Home directories, datasets, checkpoints, results | Protected by the storage system (its own RAID/erasure coding, snapshots, backups) |
9. Why /raid is RAID 0 (and why that's fine)
Why it's effective
- Aggregate bandwidth. Striping spreads each large read across all 8 drives at once, so a big sequential read gets roughly 8× one drive's throughput. That's what keeps a data loader feeding 8 GPUs.
- Aggregate IOPS. Small random reads (many small image or audio files) are spread across 8 controllers and their queues.
- All capacity usable. No space spent on mirrors or parity: ~30 TB usable from ~30 TB raw.
- No write penalty. No parity to compute or read-modify-write, so staging a dataset or writing scratch output is as fast as the drives allow.
- Simple and cheap in software. md RAID 0 has almost no CPU overhead.
Why the risk is acceptable
/raidis designed as a cache / scratch tier. Its contents are copies of data whose master lives on shared storage (or is temporary by nature).- If a drive fails, you lose cached data, not unique data: replace the drive, recreate the array, and the cache refills.
- Training jobs write checkpoints to shared storage, so a failed
/raidcosts at most a restart, not lost work.
/raid" is wrong. So is "convert /raid to RAID 5 for safety on DGX": it cuts capacity and write performance and still doesn't replace shared storage. The local array is a cache.10. Local caching techniques
FS-Cache with cachefilesd (persistent NFS cache)
Linux FS-Cache lets network filesystems (NFS) cache file data on a local disk. The cachefilesd daemon manages that cache. DGX systems use /raid as the cache location, so repeated reads of NFS-hosted datasets come from local NVMe instead of the network.
# /etc/cachefilesd.conf
dir /raid/fscache
tag dgxcache
brun 25% bcull 15% bstop 5% # start culling when free space drops
sudo systemctl enable --now cachefilesd
# Mount NFS with the fsc option to enable caching for that mount
sudo mount -t nfs -o fsc,vers=4.1 nfs01:/datasets /mnt/datasets
cat /proc/fs/fscache/stats # hit/miss counters
/mnt/datasets as usual. The first epoch pulls from NFS, and later epochs hit the local cache. It's a read cache: writes still go to the NFS server.cachefilesd with /raid/fscache. Parallel filesystems (Lustre, WEKA, Storage Scale) have their own client-side caching instead of FS-Cache.Other caching patterns
| Technique | How | When |
|---|---|---|
| Dataset staging | Copy the dataset to /raid at job start (Slurm prolog, or the job's first step) with parallel tools (rsync in parallel, parallel/mpirun copy, fpsync) | Datasets that fit in ~30 TB and are read many times |
| Page cache | Linux keeps recently read file data in spare DRAM (up to ~2 TB on DGX H100) automatically | Datasets that fit in memory get RAM-speed reads after the first pass |
| Container image cache | Point Enroot/Docker storage at /raid (for example ENROOT_CACHE_PATH, ENROOT_DATA_PATH, Docker data-root) | Big NGC images pulled once per node, not per job (see NGC mastery) |
| Scratch for job temp files | TMPDIR=/raid/tmp/$SLURM_JOB_ID, cleaned in the epilog | Shuffle buffers, compiled kernels, intermediate outputs |
| Burst buffers | A fast tier in front of the parallel FS (some storage systems or schedulers manage it) | Checkpoint bursts, write-heavy phases |
/raid fills up and the next job fails with "No space left on device." Also, jobs scheduled to a different node find a cold cache. Node-local data and scheduler placement go together.11. Shared storage: NFS and parallel filesystems
| Type | Examples | Strengths | Limits |
|---|---|---|---|
| NFS | Linux NFS server, NAS appliances | Simple, universal; home directories, software, small shared data | A single server path can bottleneck many GPU nodes; metadata-heavy workloads struggle |
| NFS over RDMA / nconnect | NFS with RDMA transport or multiple TCP connections | Much higher throughput from the same protocol | Still bounded by the server design |
| Parallel filesystems | Lustre (for example DDN EXAScaler), IBM Storage Scale (GPFS), WEKA, BeeGFS | Data striped across many servers: aggregate bandwidth scales with servers; designed for thousands of clients | More complex to run; need tuned clients |
| Scale-out NAS / all-flash | VAST, NetApp, Pure | NFS-compatible with high parallel performance | Vendor-specific features |
| Object storage | S3-compatible stores | Cheap, huge, durable; great for raw data lakes | Not POSIX; usually staged or streamed rather than mounted |
12. GPUDirect Storage (GDS)
Normally, reading a file into GPU memory goes storage → CPU memory (bounce buffer) → GPU. GPUDirect Storage lets storage DMA directly into GPU memory, skipping the CPU bounce buffer.
| Piece | Role |
|---|---|
cuFile API (libcufile) | The API applications (or frameworks like DALI, RAPIDS, PyTorch extensions) use for GDS reads and writes |
nvidia-fs kernel module | Enables the direct path (lsmod | grep nvidia_fs) |
gdscheck -p | Checks the platform: driver, filesystem support, and whether GDS is usable (in /usr/local/cuda/gds/tools/) |
gdsio | GDS I/O benchmark |
| Supported storage | Local NVMe (ext4/xfs), NVMe-oF, and many parallel filesystems / NFS over RDMA from certified vendors |
gdscheck -p and check the GDS support matrix. Without support, cuFile can fall back to a compatibility mode that still goes through CPU memory.Enabling GDS, step by step
This follows NVIDIA's GDS Installation and Troubleshooting Guide and the DGX OS 7 user guide. On a BCM cluster, make these changes in the software image (packages, modprobe files) and the category (kernel parameters), not on single nodes.
- Check the hardware path. A GDS-capable data-center GPU (A100, H100, H200, B200, L4, L40S and others; see the support matrix), supported storage (local NVMe, NVMe-oF, or a GDS-enabled filesystem such as Lustre/EXAScaler, WekaFS, Storage Scale, BeeGFS, VAST/NFS over RDMA), and a working driver:
nvidia-smi. Check PCIe placement withnvidia-smi topo -m. GDS is fastest when the NVMe drive or NIC sits under the same PCIe switch as the GPU. - IOMMU off or pass-through (x86). Check with
journalctl -k -b | grep -i iommu. NVIDIA recommendsintel_iommu=off/amd_iommu=offfor the best functionality and performance;iommu=ptis supported on some platforms (for example DGX A100). A fully enabled IOMMU isn't guaranteed to work. This step is skipped on Arm (Grace) platforms. - Disable PCIe ACS for peer-to-peer performance: kernel parameter
pci=disable_acs_redir=…, thenupdate-gruband reboot.gdscheck -preports switches that still have ACS enabled. - Storage transport drivers, only if needed. NVMe, NVMe-oF and NFS over RDMA need NVIDIA's patched storage drivers: DOCA (
doca-ofed,mlnx-nvme-dkms, plusmlnx-nfsrdma-dkmsfor NFS over RDMA), or the legacymlnxofedinstall --with-nvmf --with-nfsrdma. Runupdate-initramfs -uand reboot. Not required on DGX OS 6 or later. Don't mix MLNX_OFED and DOCA storage packages. - Install GDS. DGX OS:
sudo apt install nvidia-gds. This meta-package pulls innvidia-fs(a DKMS kernel module),libcufileandgds-tools. On other distros it comes from the CUDA repository; from CUDA 13.4,nvidia-fsis installed separately from the nvidia-fs downloads page. The kernel headers for the running kernel must be present so DKMS can build the module. - Load the module.
sudo modprobe nvidia_fs, check withlsmod | grep nvidia_fsandcat /proc/driver/nvidia-fs/stats. For RDMA filesystems,lsmod | grep nvidia_fs | grep ib_coreshows it's hooked into the RDMA stack. WekaFS and Storage Scale also neednvidia_peermemloaded (persist it with/etc/modules-load.d/). - Prepare the filesystem. Only ext4 and XFS are supported block filesystems. ext4 must be mounted with
data=orderedwritten explicitly in the mount options, or the library won't recognize it. GDS supports md RAID 0 only. NVMe devices with block-integrity capability aren't supported. For parallel filesystems, follow the vendor's GDS client settings (for Lustre, LNet multi-rail peer selection). - Configure cuFile if the defaults don't fit.
/etc/cufile.jsonis installed by the package. Edit it to list RDMA NIC IPs (rdma_dev_addr_listfor WekaFS and NFS over RDMA), set logging, toggleallow_compat_mode, or deny-list mounts. Per-application or container overrides go in a separate file pointed to byCUFILE_ENV_PATH_JSON. - Verify, then measure.
/usr/local/cuda/gds/tools/gdscheck.py -p(older releases ship agdscheckbinary). It lists each filesystem or device asnvfs/dmabuf/p2pdma(real GDS paths) orcompat, and shows IOMMU and ACS state. Thengdsio … -x 0(GDS) compared with-x 1(CPU path), andgds_stats -p <pid> -l 3while the job runs.
journalctl -k -b | grep -i iommu # want: IOMMU off (or pt where supported)
sudo apt install nvidia-gds # DGX OS; pulls nvidia-fs (DKMS), libcufile, gds-tools
sudo modprobe nvidia_fs && lsmod | grep nvidia_fs
mount | grep data=ordered # ext4 must show data=ordered explicitly
/usr/local/cuda/gds/tools/gdscheck.py -p # NVMe : nvfs (not just "compat")
/usr/local/cuda/gds/tools/gdsio -f /raid/gds/f -d 0 -w 8 -s 10G -i 1M -x 0 -I 0
cat /proc/driver/nvidia-fs/stats # GDS read/write counters climbing = real GDS
tail cufile.log # written in the app's working directory by default
sudo /bin/nvidia-relaxed-ordering-nvme.sh enable). NVMe interrupt coalescing is configured automatically by the nvidia-nvme-options package.The newer path: PCI P2PDMA (no nvidia-fs for NVMe)
On recent stacks, local NVMe can use the upstream Linux PCI P2PDMA feature instead of nvidia-fs. It needs:
- Kernel 6.2 or later.
- An Ampere-or-newer GPU on the supported list.
- NVIDIA driver options
NVreg_RegistryDwords="RMForceStaticBar1=1;RmForceDisableIomapWC=1;"on x86. - NVMe multipath disabled (
nvme_core multipath=N). "use_pci_p2pdma": trueincufile.json.
gdscheck -p then shows NVMe : p2pdma. If both paths are available, P2PDMA takes precedence. On x86, P2PDMA doesn't support RAID volumes (only Arm does). The DGX OS 7 GDS install steps are written for systems that do not use P2PDMA.
GDS exam gotchas
| Claim | Reality |
|---|---|
| "GDS data passes through host RAM / CPU caches" | False on the GDS path: storage or the NIC DMAs straight into GPU memory. The CPU still runs the control path (open, submit, completion). In compatibility mode data does go through a CPU bounce buffer. |
| "GDS only works with local NVMe" / "only with InfiniBand storage" | Both false. It covers local PCIe NVMe and remote RDMA-backed filesystems (and NVMe-oF). |
| "Loading nvidia-fs is enough" | No. The filesystem must support GDS (ext4 with explicit data=ordered, XFS, or a GDS-enabled parallel FS), RAID must be RAID 0, IOMMU/ACS must be right, and the app must use cuFile (directly or through a framework). |
| "No /etc/cufile.json means no GDS" | The package installs a default file and GDS works with its defaults. You edit it (or point CUFILE_ENV_PATH_JSON at an override) only to change behavior, for example RDMA NIC lists for WekaFS or NFS over RDMA. |
| "It's working, I got no errors" | With allow_compat_mode true (the default), cuFile silently falls back to POSIX I/O. Prove the GDS path with gdscheck -p (nvfs/dmabuf/p2pdma, not compat), /proc/driver/nvidia-fs/stats, and gdsio -x 0 beating -x 1. |
| "modprobe nvidia_fs fails with a key/permission error" | UEFI Secure Boot with a locally built (DKMS) module that isn't signed by an enrolled key. Sign it and enroll the key with MOK (mokutil), same as for the NVIDIA driver (bring-up guide). Don't just disable Secure Boot. |
| "GDS = GPUDirect RDMA" | Related but different. GPUDirect RDMA (nvidia_peermem or DMA-BUF) is NIC ↔ GPU for networking such as NCCL. GDS is storage ↔ GPU through cuFile and nvidia-fs. RDMA filesystems use both. |
| "Turn the IOMMU fully on for safety" | NVIDIA recommends off (or pt on supported platforms) for GDS on x86. A fully enabled IOMMU isn't guaranteed to work or perform. |
13. Filesystems and tuning
| Topic | Guidance |
|---|---|
| ext4 vs XFS | Both are fine on NVMe. XFS handles very large files and parallel writers well; ext4 is the common default. DGX OS formats /raid with its documented default. |
| Mount options | noatime avoids a metadata write on every read |
| I/O scheduler | NVMe usually uses none (the device handles ordering): cat /sys/block/nvme2n1/queue/scheduler |
| TRIM / discard | Tells the SSD which blocks are free, sustaining write performance. Prefer a periodic fstrim (timer) over the discard mount option. |
| Free space | Flash performance degrades when nearly full. Keep headroom on /raid. |
| NUMA locality | Run data-loader workers on CPUs local to the drives/NICs and GPUs they serve. Check with nvidia-smi topo -m and lstopo. |
| Many small files | Metadata overhead dominates. Pack samples into shards (WebDataset tar, TFRecord, Parquet). |
14. Benchmarking with fio
# Sequential read bandwidth (large blocks, many jobs, direct I/O to bypass the page cache)
fio --name=seqread --directory=/raid/fiotest --rw=read --bs=1M --size=20G \
--numjobs=16 --iodepth=32 --ioengine=libaio --direct=1 --group_reporting
# Random 4K read IOPS
fio --name=randread --directory=/raid/fiotest --rw=randread --bs=4k --size=10G \
--numjobs=16 --iodepth=64 --ioengine=libaio --direct=1 --group_reporting
# Sequential write (staging / checkpoint-like)
fio --name=seqwrite --directory=/raid/fiotest --rw=write --bs=1M --size=20G \
--numjobs=8 --iodepth=32 --ioengine=libaio --direct=1 --group_reporting
| Option | Why |
|---|---|
--direct=1 | Bypasses the page cache; otherwise you measure RAM, not disks |
--numjobs, --iodepth | Parallelism: NVMe needs many outstanding I/Os |
--bs=1M vs 4k | Bandwidth test vs IOPS test |
--directory (a file test) | Safe: creates test files. Pointing --filename at a raw device (/dev/md1) destroys the filesystem on writes. |
dd or a single cp shows a fraction of NVMe capability (one stream, shallow queue). A "slow" result from dd doesn't mean the array is slow.fio --client, IOR, or mdtest for metadata). Single-client numbers hide aggregate limits.15. Data loading and checkpointing patterns
Feeding the GPUs
- Multiple loader workers per GPU, with prefetching and pinned memory (for example PyTorch
num_workers,pin_memory=True). - Sharded datasets: fewer, larger files read sequentially beat millions of tiny files.
- GPU-side decoding with NVIDIA DALI moves JPEG/video decode and augmentation from CPUs to GPUs, which often removes a CPU bottleneck that looks like a storage problem.
- Watch for the symptom: GPU utilization dips between steps while CPU
iowaitor loader time rises.
Checkpoints
- Checkpoints must go to shared, protected storage, because a node (and its
/raid) can die at any time. - Size estimate with mixed-precision Adam: roughly ~16 bytes per parameter (weights + gradients/master weights + two optimizer moments). A 70B-parameter model is about 1.1 TB per full checkpoint.
- Patterns: asynchronous checkpointing (write in the background while training continues), sharded checkpoints (every rank writes its part in parallel), writing locally first and then copying to shared storage, and keeping only the last N.
15b. Loading model weights across a cluster
A job can't start until its weights are in GPU memory. On one node that's a file read; across dozens of nodes it's a storage and network event.
The problem: a thundering herd
A 70B-parameter model in BF16 is about 140 GB (2 bytes per parameter). If 32 inference replicas each read the full file from shared storage at the same moment, that's about 4.5 TB requested in one burst. NFS on the in-band network collapses under that. A parallel filesystem handles it far better, but it still competes with every other job's checkpoint traffic. Load time becomes start-up time, and for autoscaled inference it becomes user-visible latency.
What each GPU actually needs
| Parallelism | What a GPU holds | Load consequence |
|---|---|---|
| Tensor / pipeline parallel | Only its slice (a fraction of each layer, or a range of layers) | With a sharded checkpoint format, each rank reads only its own bytes. Nobody needs the whole file. |
| Data parallel replicas | Each replica (one TP×PP group) holds a full copy of the model | Replicas read the same bytes again and again. This is the duplication that caching or broadcast removes. |
| Sharded data parallel (FSDP, ZeRO-3) | A slice of parameters and optimizer state per rank | Resume reads are spread across all ranks, much like tensor parallelism |
Two loading patterns
| Staged local cache | Direct sharded streaming | |
|---|---|---|
| How | Copy the weights to each node's /raid once, then every GPU loads from local NVMe | Each rank reads its own shard straight from the parallel filesystem in parallel |
| Tools | Slurm prolog or sbcast (copies a file to local disk on every allocated node); Kubernetes init container or DaemonSet that warms a hostPath cache; NIM's model cache (NIM_CACHE_PATH) on local disk or a shared volume | Distributed checkpoint formats (PyTorch Distributed Checkpoint, Megatron/NeMo distributed checkpoints) where each rank writes and reads its own files |
| Network | Storage fabric (or in-band from NGC/Hugging Face) once per node, then local PCIe | Storage fabric on every load, spread across many storage servers |
| Best for | Inference fleets, autoscaling, repeated restarts of the same model, fine-tuning from a fixed base | Large training jobs resuming from their own recent checkpoint (written moments ago, never cached anywhere) |
| Watch out | Cache is lost if /raid is wiped or the node is replaced, and stale versions need invalidation | Needs a parallel FS sized for the burst; NFS can't do this |
- File format matters.
safetensorsfiles can be memory-mapped, so a rank reads only the tensors it needs instead of deserialising the whole file. Old pickle-based.bincheckpoints are loaded whole. - GDS (section 12) can move weights from NVMe or a supported parallel FS straight into GPU memory, skipping the CPU bounce buffer.
- Some loaders read once per node, or once per replica group, and broadcast to the other GPUs over NVLink or the compute fabric, which trades storage reads for fast GPU-to-GPU copies.
- Don't keep weights in
$HOME, pull them from the internet in every job, or make every rank read the full file and then throw most of it away.
16. The scenario
A BCM-managed DGX cluster is already in production, and the root partition on the compute nodes' local OS drives turns out to be too small. How do you grow it so the new size sticks on every node, including after reboots, reprovisioning, and future node replacements?
Three ideas drive the answer:
- The nodes are managed by Base Command Manager: same pattern as node recovery. The head node is the source of truth.
- "Persistent": the change must survive reboots and reprovisioning, so it has to live in the central definition, not just on the node.
- "Operating system partition": this is a disk and OS topic. GPU tools (DCGM, nvidia-smi) don't belong here.
17. Quick recap: BCM, the head node, and software images
- BCM (NVIDIA Base Command Manager, formerly Bright Cluster Manager) runs on the head node and manages all compute nodes centrally.
- A software image (for example
/cm/images/dgx-imageon the head node) is the master copy of a node's OS: files, drivers, packages, and config. - Nodes are grouped into categories. A category says "these nodes use this image, this disk layout, and these settings."
- When a node boots (over the network with PXE), BCM's node installer makes the node's disk match what the head node says it should be.
18. Where BCM keeps the partition layout
BCM stores the partition layout as part of the node's provisioning definition on the head node, not on the node. In BCM this is the disk setup: an XML description of disks, partitions, sizes, filesystems, mount points, and software RAID. It's attached to the category (or to an individual node as an override), and it's used together with the software image whenever the node is provisioned.
<!-- simplified idea of a BCM disk setup -->
<diskSetup>
<device>
<blockdev>/dev/nvme0n1</blockdev>
<partition id="efi"> <size>512M</size> <filesystem>fat</filesystem> <mountPoint>/boot/efi</mountPoint> </partition>
<partition id="root"> <size>200G</size> <filesystem>ext4</filesystem> <mountPoint>/</mountPoint> </partition>
<partition id="var"> <size>max</size> <filesystem>ext4</filesystem> <mountPoint>/var</mountPoint> </partition>
</device>
<!-- plus RAID definitions, e.g. the OS mirror and the /raid stripe -->
</diskSetup>
The idea to remember is that both the OS contents and the disk layout (including RAID) are defined centrally on the head node.
19. What "reprovisioning" means (AUTO vs FULL)
Provisioning means putting the OS onto a node. Reprovisioning means doing it again so the node picks up a changed definition.
| Install mode | What the node installer does | When it's used |
|---|---|---|
AUTO (default) | Checks that the existing partitions match the disk setup. If they match, it syncs only the changed files from the image (fast). If they don't match, it falls back to a full install. | Normal reboots |
FULL | Repartitions the disk according to the disk setup, creates fresh filesystems, and copies the whole image. Local data on those partitions is wiped. | New nodes, corrupted disks, partition layout changes |
NOSYNC | Doesn't touch the disk. | Rare special cases |
20. Protecting /raid and other local data
- BCM's image sync works by copying the software image onto the node. Directories holding node-local data (such as
/raid, local scratch, caches) must be excluded from sync, or a sync could delete their contents. - BCM categories carry exclude lists for this (for example separate lists for normal image updates, sync installs, and full installs).
- The disk setup can define the
/raidarray so routine (AUTO) boots leave its data alone, while a FULL install rebuilds it as part of the layout.
cmsh
% category use dgx-h100
% show # look for exclude-list properties for sync/update/full install
% set excludelistupdate # opens an editor; e.g. ensure "- /raid/*" style entries exist
% commit
/raid is a cache, losing it in a FULL reprovision is acceptable. But exclude it from routine syncs so normal reboots and image updates don't throw away a warm cache.21. Why fixing nodes by hand over SSH backfires
The by-hand approach (SSH in and run parted / resize2fs on each node) feels natural, but in BCM it's wrong for several reasons:
- It isn't persistent. The head node still has the old layout. The next time BCM reprovisions that node (a new node, a reinstall after a failure, or AUTO noticing the partitions don't match), it rebuilds the disk to the old size and your change is gone.
- It causes configuration drift. Some nodes end up resized and some don't, so the nodes are no longer identical, which is exactly what BCM exists to prevent.
- It doesn't scale. Doing it by hand on 32, 128, or 1000 DGX nodes is slow and error-prone.
- It's risky. Resizing a live root partition (on top of an md mirror) by hand can corrupt the filesystem. BCM's reprovisioning builds the layout cleanly from a known definition.
22. Know your tools: which ones touch storage?
| Tool | What it's for | Storage role |
|---|---|---|
BCM (cmsh, Base View) | Provisioning nodes, software images, disk layout, categories, exclude lists | Defines node storage layout centrally |
mdadm, /proc/mdstat | Software RAID create, inspect, rebuild | RAID state on a node |
| nvme-cli | NVMe inventory, SMART health, firmware, erase | Drive health |
| nvsm | DGX system health, including drives and RAID | Health reporting |
| parted / resize2fs | Low-level partition and filesystem tools on one machine | Single-node only; not persistent under BCM |
| fio / gdsio | Storage benchmarks | Performance measurement |
DCGM (dcgmi) | GPU monitoring, health checks, diagnostics | None. "DCGM storage policies" isn't a thing. |
| nvidia-smi | Querying and configuring GPUs | None. It doesn't partition disks. |
23. Weighing the common approaches
parted and resize2fs
These are real tools and would work on a standalone server, but in BCM the change isn't persistent: the head node's definition still has the old layout and will put it back on the next reprovision. It also causes drift between nodes and doesn't scale.
DCGM is for GPU monitoring and diagnostics. It has no ability to partition disks or set storage quotas.
This follows BCM's model: change the central definition on the head node, then reprovision the nodes so they're rebuilt to match. The change is persistent, consistent across all nodes, and repeatable for new or replacement nodes.
nvidia-smi to reassign local disk space set aside for GPU offload
nvidia-smi configures GPUs (clocks, power, MIG, ECC), not SSD partitions. Disk space "set aside for GPU offload" isn't something nvidia-smi configures.
24. What the real procedure looks like
- Drain the nodes in Slurm so no jobs are running on them:
scontrol update nodename=dgx[01-04] state=drain reason="repartition OS disk" - Back up anything stored only on the nodes' local disks (ideally nothing:
/raidis a cache). - Edit the disk layout on the head node for the category:
(If the OS contents also need to change, update the software image on the head node too.)cmsh % category use dgx-h100 % set disksetup # opens the disk setup XML in an editor: change the root partition size % commit - Tell BCM the nodes need a full install on their next boot:
% device use dgx01 % set nextinstallmode full % commit - Reboot the nodes (BCM power control through the BMC; see Redfish & BMC). They PXE boot, and the node installer repartitions the disks with the new layout and copies the image.
- Verify on a node (
lsblk,df -h,cat /proc/mdstat), then resume the nodes in Slurm.
Any new or replacement DGX added to that category later gets the new layout automatically. That's the payoff of doing it centrally.
25. How to spot the right answers on similar questions
- "Managed by BCM" + "persistent" / "consistent" / "all nodes": the answer is almost always change it on the head node (image, category, disk setup), then sync or reprovision.
- "SSH to each node and…": in a BCM question this is usually wrong.
- Small file or package change: update the image, then sync (no full reinstall needed).
- Partition or disk layout change: update the disk layout, then do a FULL reprovision.
- A GPU tool (DCGM, nvidia-smi) offered for a non-GPU task: distractor.
- "Where should checkpoints go?": shared storage, never only
/raid. - "Why is
/raidRAID 0?": performance + full capacity for a re-creatable cache.
26. "Where should this data live?" chooser
27. Sample outputs
What the commands in this guide print. Expand a command to see a typical result and what to check in it.
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTDisks, partitions, RAID, mounts
NAME SIZE TYPE FSTYPE MOUNTPOINT
nvme0n1 1.7T disk
├─nvme0n1p1 512M part vfat /boot/efi
└─nvme0n1p2 1.7T part linux_raid_member
└─md0 1.7T raid1 ext4 /
nvme1n1 1.7T disk
├─nvme1n1p1 512M part vfat
└─nvme1n1p2 1.7T part linux_raid_member
└─md0 1.7T raid1 ext4 /
nvme2n1 3.5T disk linux_raid_member
└─md1 27.9T raid0 ext4 /raid
nvme3n1 3.5T disk linux_raid_member
└─md1 27.9T raid0 ext4 /raid
...
nvme9n1 3.5T disk linux_raid_member
└─md1 27.9T raid0 ext4 /raidWhat to look at: Expect / on md0 (raid1 over the two M.2 drives) and /raid on md1 (raid0 over the eight U.2 drives, about 28T). A data drive with no md1 under it, or /raid missing its mount point, means the array is incomplete or not mounted.
sudo nvme listAll NVMe drives: model, size, firmware
Node SN Model Namespace Usage Format FW Rev
--------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 S6EXNE0T100001 SAMSUNG MZ1L21T9HCLS-00A07 1 1.92 TB / 1.92 TB 512 B + 0 B GDC7302Q
/dev/nvme1n1 S6EXNE0T100002 SAMSUNG MZ1L21T9HCLS-00A07 1 1.92 TB / 1.92 TB 512 B + 0 B GDC7302Q
/dev/nvme2n1 X1A0A0EXAMPL KIOXIA KCM6DRUL3T84 1 3.84 TB / 3.84 TB 512 B + 0 B 0107
/dev/nvme3n1 X1A0A0EXAMPM KIOXIA KCM6DRUL3T84 1 3.84 TB / 3.84 TB 512 B + 0 B 0107
...
/dev/nvme9n1 X1A0A0EXAMPT KIOXIA KCM6DRUL3T84 1 3.84 TB / 3.84 TB 512 B + 0 B 0106What to look at: A DGX H100 should list 10 drives: two 1.92 TB boot M.2 and eight 3.84 TB data U.2. A missing drive or one with a different FW Rev (nvme9n1 here) is a finding to fix before acceptance.
sudo nvme smart-log /dev/nvme2Drive health and endurance
Smart Log for NVME device:nvme2 namespace-id:ffffffff
critical_warning : 0
temperature : 38 C (311 Kelvin)
available_spare : 100%
available_spare_threshold : 10%
percentage_used : 3%
endurance group critical warning summary: 0
data_units_read : 412,904,113
data_units_written : 98,233,710
host_read_commands : 3,301,882,019
host_write_commands : 905,771,402
controller_busy_time : 1,894
power_cycles : 41
power_on_hours : 6,512
unsafe_shutdowns : 4
media_errors : 0
num_err_log_entries : 0
Warning Temperature Time : 0
Critical Composite Temperature Time : 0What to look at: critical_warning and media_errors should both be 0; any non-zero critical_warning means act now. Watch percentage_used for wear (it can exceed 100%) and available_spare dropping toward its threshold.
sudo nvme id-ctrl /dev/nvme2 | grep -E 'mn|fr'Drive model and firmware revision
mn : KIOXIA KCM6DRUL3T84
fr : 0107
frmw : 0x17
mntmt : 273What to look at: mn is the model and fr the firmware revision; compare fr across all data drives and nodes. The extra lines (frmw, mntmt) only match the grep pattern and can be ignored.
sudo nvsm show healthDGX health summary incl. drives
Checks
------
Verify installed DIMM memory sticks ...................... Healthy
Number of logical CPU cores [224] ........................ Healthy
Verify chassis fan presence .............................. Healthy
...
Check SMART status of NVMe device nvme2n1 ................ Healthy
Check SMART status of NVMe device nvme9n1 ................ Healthy
Verify md0 RAID array status ............................. Healthy
Verify md1 RAID array status ............................. Healthy
Verify GPU 0000:1b:00.0 link speed [32GT/s] .............. Healthy
...
Health Summary
--------------
205 out of 205 checks are healthy
0 out of 205 checks are unhealthy
0 out of 205 checks are unknown
0 out of 205 checks are informational
Overall system status is HealthyWhat to look at: The summary should read Overall system status is Healthy with 0 unhealthy checks. Any Unhealthy SMART or RAID line names the drive or array to investigate, and nvsm dump health collects it for support.
cat /proc/mdstatState of all md RAID arrays
Personalities : [raid1] [raid0] [linear] [multipath] [raid6] [raid5] [raid4] [raid10]
md1 : active raid0 nvme9n1[7] nvme8n1[6] nvme7n1[5] nvme6n1[4] nvme5n1[3] nvme4n1[2] nvme3n1[1] nvme2n1[0]
30004846592 blocks super 1.2 512k chunks
md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
1874715648 blocks super 1.2 [2/2] [UU]
bitmap: 3/14 pages [12KB], 65536KB chunk
unused devices: <none>What to look at: md0 should show [2/2] [UU]; [2/1] [U_] means the OS mirror is degraded and running on one drive. RAID 0 has no redundancy indicator, so for md1 check that all eight members are listed.
sudo mdadm --detail /dev/md0Array state, members, failed devices
/dev/md0:
Version : 1.2
Creation Time : Mon Oct 5 10:12:44 2026
Raid Level : raid1
Array Size : 1874715648 (1787.86 GiB 1919.71 GB)
Used Dev Size : 1874715648 (1787.86 GiB 1919.71 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Intent Bitmap : Internal
Update Time : Tue Nov 10 19:05:12 2026
State : clean, degraded
Active Devices : 1
Working Devices : 1
Failed Devices : 1
Spare Devices : 0
Consistency Policy : bitmap
Name : dgx01:0 (local to host dgx01)
UUID : 3a1f9c2e:5b7d4e10:9c8a7b6d:1e2f3a4b
Events : 4821
Number Major Minor RaidDevice State
0 259 2 0 active sync /dev/nvme0n1p2
- 0 0 1 removed
1 259 5 - faulty /dev/nvme1n1p2What to look at: A healthy mirror shows State : clean with 2 active devices and two active sync rows. Here State is clean, degraded and nvme1n1p2 is faulty, so that member must be removed, the drive replaced, and the new partition added back.
sudo mdadm /dev/md0 --fail /dev/nvme1n1p2 --remove /dev/nvme1n1p2Remove a failed mirror member
mdadm: set /dev/nvme1n1p2 faulty in /dev/md0
mdadm: hot removed /dev/nvme1n1p2 from /dev/md0What to look at: Both lines should appear before you pull the drive. "Device or resource busy" on remove means the member was not marked faulty first.
sudo mdadm /dev/md0 --add /dev/nvme1n1p2Re-add a drive and start rebuild
mdadm: added /dev/nvme1n1p2
$ cat /proc/mdstat
md0 : active raid1 nvme1n1p2[2] nvme0n1p2[0]
1874715648 blocks super 1.2 [2/1] [U_]
[===>.................] recovery = 17.4% (326201344/1874715648) finish=41.2min speed=626104K/sec
bitmap: 3/14 pages [12KB], 65536KB chunkWhat to look at: A recovery progress bar means the rebuild started; the array stays [U_] until it reaches 100% and then shows [UU]. If no recovery line appears, the new partition is likely too small or the wrong device.
cat /proc/fs/fscache/statsFS-Cache hit/miss counters
FS-Cache statistics
Cookies: idx=3 dat=12873 spc=0
Objects: alc=12850 nal=0 avl=12850 ded=0
ChkAux : non=0 ok=0 upd=0 obs=0
Pages : mrk=1532876 unc=0
Acquire: n=12876 nul=0 noc=0 ok=12876 nbf=0 oom=0
Lookups: n=12850 neg=12840 pos=10 crt=12840 tmo=0
Invals : n=0 run=0
Updates: n=0 nul=0 run=0
Relinqs: n=24 nul=0 wcr=0 rtr=0
Retrvls: n=482391 ok=401220 wt=1203 nod=81171 nbf=0 int=0 oom=0
Retrvls: ops=482391 owt=2 abt=0
Stores : n=81171 ok=81171 agn=0 nbf=0 oom=0
Stores : ops=81171 run=162342 pgs=81171 rxd=81171 olm=0
...What to look at: On Retrvls, ok counts pages served from the local cache and nod counts misses that went to NFS; ok should climb on the second epoch. All zeros means the NFS mount lacks the fsc option or cachefilesd isn't running.
journalctl -k -b | grep -i iommuIOMMU state for GPUDirect Storage
Nov 10 08:12:01 dgx01 kernel: Command line: BOOT_IMAGE=/boot/vmlinuz-5.15.0-1063-nvidia root=/dev/md0 ro intel_iommu=off console=tty0
Nov 10 08:12:01 dgx01 kernel: Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.15.0-1063-nvidia root=/dev/md0 ro intel_iommu=off console=tty0
Nov 10 08:12:01 dgx01 kernel: DMAR: IOMMU disabledWhat to look at: For GDS through nvidia-fs you want IOMMU disabled (or pass-through where supported). Lines like "DMAR: IOMMU enabled" or "Default domain type: Translated" mean P2P DMA goes through the IOMMU and GDS may fall back or fail.
sudo modprobe nvidia_fs && lsmod | grep nvidia_fsLoad and confirm the GDS kernel module
nvidia_fs 266240 0What to look at: One nvidia_fs line means the module is loaded. No output, or "Key was rejected by service" from modprobe, usually means Secure Boot is blocking an unsigned DKMS module.
mount | grep data=orderedext4 journal mode for GDS
/dev/md1 on /raid type ext4 (rw,relatime,stripe=256,data=ordered)What to look at: GDS on ext4 needs data=ordered to appear explicitly in the mount options. If /raid is missing from this output, add data=ordered to its fstab or BCM fsmount options and remount.
/usr/local/cuda/gds/tools/gdscheck.py -pIs GPUDirect Storage usable here?
GDS release version: 1.7.2.11
nvidia_fs version: 2.17 libcufile version: 2.12
Platform: x86_64
============
ENVIRONMENT:
============
=====================
DRIVER CONFIGURATION:
=====================
NVMe P2PDMA : Unsupported
NVMe : Supported
NVMeOF : Unsupported
SCSI : Unsupported
...
NFS : Unsupported
WekaFS : Unsupported
Userspace RDMA : Unsupported
--Mellanox PeerDirect : Enabled
--rdma library : Not Loaded (libcufile_rdma.so)
=====================
CUFILE CONFIGURATION:
=====================
properties.use_pci_p2pdma : false
properties.use_compat_mode : true
properties.force_compat_mode : false
...
=========
GPU INFO:
=========
GPU index 0 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
...
GPU index 7 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
==============
PLATFORM INFO:
==============
IOMMU: disabled
Nvidia Driver Info Status: Supported(Nvidia Open Driver Installed)
Platform verification succeededWhat to look at: NVMe : Supported, every GPU "supports GDS", and Platform verification succeeded are what you want. Unsupported for your filesystem, "Found ACS enabled for switch", or IOMMU: enabled mean I/O will silently use compat mode while use_compat_mode is true.
/usr/local/cuda/gds/tools/gdsio -f /raid/gds/f -d 0 -w 8 -s 10G -i 1M -x 0 -I 0GDS read throughput test
IoType: READ XferType: GPUD Threads: 8 DataSetSize: 10485760/10485760(KiB) IOSize: 1024(KiB) Throughput: 12.851403 GiB/sec, Avg_Latency: 607.312500 usecs ops: 10240 total_time 0.778164 secsWhat to look at: XferType GPUD means the GPU-direct path (-x 0). Rerun with -x 1 (CPU path); if GPUD isn't clearly faster, or the run errors with compat mode disabled, GDS isn't really active.
cat /proc/driver/nvidia-fs/statsGDS driver counters
GDS Version: 1.7.2.11
NVFS statistics(ver: 4.0)
NVFS Driver(version: 2.17.5)
Mellanox PeerDirect Supported: True
IO stats: Disabled, peer IO stats: Disabled
Logging level: info
Active Shadow-Buffer (MiB): 0
Active Process: 0
Reads : err=0 io_state_err=0
Sparse Reads : n=0 io=0 holes=0 pages=0
Writes : err=0 io_state_err=0 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0
Mmap : n=8 ok=8 err=0 munmap=8
Bar1-map : n=8 ok=8 err=0 free=8 callbacks=0 active=0 delay-frees=0
Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0
Ops : Read=10240 Write=0 BatchIO=0What to look at: The Ops Read and Write counters should climb while a GDS job runs; if they stay at 0, the application is using the POSIX compat path. Non-zero err values or Error counters point to driver or DMA mapping problems.
fio --name=seqread --directory=/raid/fiotest --rw=read --bs=1M --size=20G --numjobs=16 --iodepth=32 --ioengine=libaio --direct=1 --group_reportingSequential read bandwidth of /raid
seqread: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=32
...
fio-3.28
Starting 16 processes
Jobs: 16 (f=16): [R(16)][100.0%][r=48.6GiB/s][r=49.8k IOPS][eta 00m:00s]
seqread: (groupid=0, jobs=16): err= 0: pid=40211: Tue Nov 10 19:40:02 2026
read: IOPS=49.1k, BW=47.9GiB/s (51.5GB/s)(320GiB/6676msec)
slat (usec): min=8, max=1210, avg=21.40, stdev=9.85
clat (usec): min=412, max=48121, avg=10392.11, stdev=2101.66
lat (usec): min=431, max=48140, avg=10413.62, stdev=2101.70
clat percentiles (usec):
| 1.00th=[ 5604], 5.00th=[ 7111], 50.00th=[10421], 95.00th=[13829],
| 99.00th=[16581], 99.90th=[21890], 99.99th=[37487]
cpu : usr=0.61%, sys=6.12%, ctx=318201, majf=0, minf=8457
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
...
Run status group 0 (all jobs):
READ: bw=47.9GiB/s (51.5GB/s), 47.9GiB/s-47.9GiB/s (51.5GB/s-51.5GB/s), io=320GiB (344GB), run=6676-6676msec
Disk stats (read/write):
md1: ios=327012/0, merge=0/0, ticks=3391201/0, in_queue=3391201, util=99.71%, aggrUtil=99.60%What to look at: Read the BW on the READ summary line and compare it to the node's baseline and to other nodes. err= must be 0, and a node far below its peers usually has a missing RAID member, a drive at reduced PCIe link, or a test that hit the page cache without --direct=1.
cmsh -c "category use dgx-h100; get excludelistupdate"Paths BCM won't touch on imageupdate
# Exclude list for imageupdate (sync from image to running node)
- /cm/shared/*
- /home/*
- /proc/*
- /sys/*
- /dev/*
- /tmp/*
- /raid/*
- /var/log/*
- /var/spool/*
- /var/lib/docker/*
...What to look at: /raid/* must be on the update and sync exclude lists, or an imageupdate can delete the node-local cache. A missing /home/* or /cm/shared/* entry is equally dangerous because those are shared mounts.
scontrol update nodename=dgx[01-04] state=drain reason="repartition OS disk"Drain nodes before repartitioning
(no output on success)
$ sinfo -R
REASON USER TIMESTAMP NODELIST
repartition OS disk root 2026-11-10T19:45:12 dgx[01-04]What to look at: Success prints nothing; confirm with sinfo -R that the nodes show your reason. Wait until running jobs finish and the nodes show drained (not draining) before setting a FULL install.
[bcm-head01->device[dgx01]]% set nextinstallmode fullOne-time FULL reinstall on next boot
[bcm-head01->device[dgx01]]% set nextinstallmode full
[bcm-head01->device*[dgx01*]]% commit
[bcm-head01->device[dgx01]]% get nextinstallmode
FULL
[bcm-head01->device[dgx01]]% get installmode
AUTOWhat to look at: nextinstallmode applies to the next boot only and is cleared afterwards, while installmode stays AUTO. Setting installmode itself to FULL would wipe and repartition the node, including /raid, on every boot.
28. Scenarios
29. Searchable reference
| Item | Meaning |
|---|
30. Flashcards (click to flip)
31. Exam traps
- DGX
/raidis RAID 0 (speed + capacity for a cache); the OS drives are RAID 1. - RAID 0 survives zero drive failures. RAID 1 survives n−1. RAID 5 one, RAID 6 two.
- RAID is not a backup.
- Checkpoints and results go to shared storage, never only to
/raid. - DGX uses software RAID (mdadm):
cat /proc/mdstat,mdadm --detail. [U_]in/proc/mdstat= degraded mirror.- NFS caching on DGX: cachefilesd +
/raid/fscache+ mount optionfsc. - GPUDirect Storage: storage → GPU memory directly through cuFile /
nvidia-fs; check withgdscheck -p. fio --direct=1to avoid measuring the page cache; NVMe needs parallelism (numjobs, iodepth).- NVMe health:
nvme smart-log(critical_warning,percentage_used,media_errors). - BCM layout change → edit disk setup on the head node → FULL install. SSH + parted isn't persistent.
- Exclude
/raidfrom image syncs so routine updates don't wipe the cache. - DCGM and nvidia-smi don't manage disks.
- Keep storage traffic on the storage network, not the GPU compute fabric.
- The DGX OS lives on the M.2 RAID 1 mirror, not on
/raid./raidis cache and scratch. $HOMEis NFS over in-band. It's not the place for datasets, checkpoints, or model weights.- With tensor/pipeline parallelism each GPU loads only its shard. Duplicate reads come from data-parallel replicas, which is what local caching fixes.
- Object storage (S3) isn't a POSIX working directory: stage or stream from it.
- GDS: no errors ≠ GDS active. Compatibility mode silently uses the CPU path; check
gdscheck -pfor nvfs/dmabuf/p2pdma. - GDS prerequisites beyond
nvidia-fs: IOMMU off/pt on x86, ACS disabled, ext4 with explicitdata=orderedor XFS, RAID 0 only, and a cuFile-using app.
32. Practice quiz (34 questions)
33. Glossary
| Term | Meaning |
|---|---|
| Partition / filesystem | A slice of a disk / the structure inside it that stores files (ext4, xfs). |
| NVMe / namespace | Flash storage protocol over PCIe / a logical disk exposed by an NVMe controller. |
| M.2 / U.2 | NVMe form factors: small internal stick (DGX OS) / 2.5" hot-swap drive (DGX data). |
| DWPD / TBW | SSD endurance ratings: drive writes per day / total terabytes written. |
| RAID 0 / 1 / 5 / 6 / 10 | Stripe / mirror / single parity / double parity / striped mirrors. |
| mdadm / md | Linux software RAID tool / kernel driver (/dev/mdX). |
| /raid | DGX local data array (RAID 0 of U.2 NVMe), used as cache/scratch. |
| FS-Cache / cachefilesd | Kernel caching layer for network filesystems / the daemon managing the on-disk cache. |
| Page cache | File data cached in spare RAM by the Linux kernel. |
| Parallel filesystem | Storage striped across many servers for aggregate bandwidth (Lustre, Storage Scale, WEKA, BeeGFS). |
| NVMe-oF | NVMe over Fabrics (RDMA or TCP). |
| GPUDirect Storage / cuFile / nvidia-fs | Direct storage↔GPU DMA / its API / its kernel module. |
| fio | Flexible I/O tester for storage benchmarks. |
| DALI | NVIDIA Data Loading Library: GPU-accelerated decode and augmentation. |
| BCM / head node / software image / category | Cluster manager / its central server / master OS tree / group of nodes sharing image and settings. |
| Disk setup | BCM's XML definition of a node's partitions, filesystems, mount points, and RAID. |
| AUTO / FULL install, nextinstallmode | Sync if layout matches / repartition and copy everything; the setting forcing the next mode. |
| Exclude lists | BCM category settings that keep node-local paths (like /raid) from being overwritten by image sync. |
| Configuration drift | Nodes becoming different from each other because of manual, local changes. |
| Drain (Slurm) | Stop scheduling new jobs on a node so it can be safely maintained. |