Category: nvidia

  • Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 3: RDMA Performance Testing

    Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 3: RDMA Performance Testing

    Before moving on to Part 3 of this project, lets review what we have accomplished thus far.

    In Part 1 and Part 2 we have…

    • Did a bit of planning and scoping
    • Built a 3-node GPU cluster (viper, columbia, prometheus)
    • Interconnected with InfiniBand Installed and validated ConnectX-4 NICs and RDMA stack (mlx5, ib_core, etc.)
    • Brought up the InfiniBand fabric using OpenSM (links active, LIDs assigned)
    • Verified topology and connectivity (ibstat, ibnetdiscover)
    • Configured IP over InfiniBand for basic networking between nodes Identified PCIe/NUMA limitations affecting optimal GPU↔NIC performance

    We are now ready to do some performance testing of our Infiniband network.


    Pre-Test Setup

    Before we can get started on our perf testing we have bit of work to do. We are going to install a few packages, and configure some tunables.

    Diagnostic Tools

    First lets make sure that we have a couple tools installed, so lets install some rpms.

    sudo dnf install infiniband-diags libibverbs-utils librdmacm-utils -y

    Kernel Modules

    InfiniBand and GPUDirect require specific modules to load at boot. So lets create hpc.conf in /etc/modules-load.d/. This creates (or overwrites) /etc/modules-load.d/hpc.conf. This file ensures each module loads automatically at boot via systemd-modules-load. Run this on each host.

    sudo tee /etc/modules-load.d/hpc.conf >/dev/null <<'EOF'
    ib_ipoib
    ib_umad
    ib_uverbs
    nvidia-peermem
    EOF

    Then force load the modules.

    sudo modprobe ib_ipoib ib_umad ib_uverbs nvidia-peermem

    Below is a short breakdown/description for each module.

    ModuleHow it’s used
    ib_ipoibProvides IP networking over InfiniBand (e.g., ib0) for SSH, NFS, TCP/IP
    ib_umadEnables userspace IB management tools (e.g., ibstat, fabric queries)
    ib_uverbsCore RDMA interface used by applications (MPI, NCCL, libibverbs)
    nvidia-peermemEnables GPUDirect RDMA for direct GPU ↔ NIC memory transfers (no CPU copy)

    Locked Memory Limits

    RDMA works by “pinning” memory so the OS cannot swap it to disk. So we need to create /etc/security/limits.d/99-hpc.conf as shown below.

    sudo tee /etc/security/limits.d/99-hpc.conf >/dev/null <<'EOF'
    * soft memlock unlimited
    * hard memlock unlimited
    EOF

    Performance & RDMA Benchmarking

    Health Check

    First lets run the following commands on any host under test, just to make sure the InfiniBand network is healthy before we start any testing. Run each line individually and make note of the output.

    hostname
    ibstat
    ibv_devinfo | egrep 'hca_id|transport|fw_ver|port:|link_layer|active_mtu|sm_lid|port_lid'

    You are specifically interesting in the following

    • Device Present (mlx5)
    • State: Active
    • Physical state: LinkUp
    • Link layer: InfiniBand

    Confirm HCA Name and Port Number

    Run on any device under test – we will need this for our test on our receiver and sender side.

    ibv_devices

    Output from columbia.lab.

     device          	   node GUID
     ------          	----------------
     mlx5_0          	248a070300ac5414
    
    

    Output from prometheus.lab

     device          	   node GUID
     ------          	----------------
     mlx5_0          	248a070300ac5610
    
    

    Run the RDMA Latency Test

    For our ib_send_lat (latency test) our device IP addresses are as follows.

    • columbia.lab – 172.16.50.12
    • prometheus.lab -172.16.50.11

    On our first device, columbia.lab, we run the following and leave it running.

    ib_send_lat -d mlx5_0 -i 1

    Now over on prometheus, run the command below. Insert the IP from columbia captured above. You will see a good bit of output in your terminal window.

    ib_send_lat -d mlx5_0 -i 1 <columbia_ip>

    Key configuration details

    So assuming the test did not fail, you are going to see some data spit out. Lets make sense of some of it.

    ParameterValueMeaning
    Devicemlx5_0ConnectX-4 (mlx5 driver)
    TransportIB (RC)Reliable Connection (standard RDMA mode)
    MTU4096Optimal for IB performance
    Queue Pairs1Single stream test
    Inline data236BSmall messages optimized
    Link typeInfiniBandCorrect mode

    What this test is actually doing

    ib_send_lat:

    • Registers memory with the NIC
    • Creates RDMA queue pairs
    • Sends messages using:
      • ibv_post_send()
    • Measures completion latency via completion queues (CQs)

    This is direct RDMA messaging, not IP networking.

    Our Overall results

    • Average latency: ~1.15 µs
    • Typical latency: ~1.14 µs
    • Minimum latency: 1.06 µs
    • Outliers: up to 11.41 µs
    • Conclusion: Healthy RDMA performance

    While InfiniBand ≠ RDMA test by default, our test ib_send_lat specifically uses RDMA verbs, so a successful result proves RDMA is working.

    In the output above, our average latency confirms that RDMA is functioning, as is kernel bypass. Note, that while we are using TCP/IP to setup the test, the actual data transfer is NIC to NIC and memory to memory. The queue pair exchange confirms RDMA session, as QPs were created on both nodes and transitioned through the required queue pair states shown below.

    StateNamePurposeAnalogy
    INITInitializeLocal QP setupPhone powered on
    RTRReady to ReceiveCan receive remote dataYou know the other person’s number
    RTSReady to SendFully operational (send + receive)Call connected and talking

    Run the RDMA Bandwidth Test

    For this test we will run ib_send_bw. This test measures the following.

    • Throughput (bandwidth) of RDMA send operations
    • NIC-to-NIC data transfer rate
    • Memory → NIC → fabric → NIC → memory

    Again this test uses IP to establish the initial connection between nodes, but make no mistake we are using RDMA verbs and are testing IB traffic (not IP traffic).

    So over on our first node (columbia.lab) we run the following.

    ib_send_bw -d mlx5_0 -i 1 -a

    Why these flags

    FlagPurpose
    -d mlx5_0Select your ConnectX-4 device
    -i 1Use IB port 1
    -aSweep all message sizes

    And on our second node we run the command shown below.

    ib_send_bw -d mlx5_0 -i 1 -a <columbia_ip>

    Assuming that this command does not fail, you will see a bunch of output that we need to interpret. This output is truncated, but I wanted to give you an idea of what to expect in the output.

    ib_send_bw -d mlx5_0 -i 1 -a 172.16.50.12
    ---------------------------------------------------------------------------------------
    Send BW Test
    Dual-port : OFF Device : mlx5_0
    Number of qps : 1 Transport type : IB
    Connection type : RC Using SRQ : OFF
    PCIe relax order: ON Lock-free : OFF
    WARNING: CPU is not PCIe relaxed ordering compliant.
    WARNING: You should disable PCIe RO with `--disable_pcie_relaxed` for both server and client.
    ibv_wr* API : ON Using DDP : OFF
    TX depth : 128
    CQ Moderation : 100
    CQE Poll Batch : 16
    Mtu : 4096[B]
    Link type : IB
    Max inline data : 0[B]
    rdma_cm QPs : OFF
    Data ex. method : Ethernet
    ---------------------------------------------------------------------------------------
    local address: LID 0x02 QPN 0x0107 PSN 0xed831e
    remote address: LID 0x01 QPN 0x0107 PSN 0xa2c511
    ---------------------------------------------------------------------------------------
    #bytes #iterations BW peak[MiB/sec] BW average[MiB/sec] MsgRate[Mpps]
    Conflicting CPU frequency values detected: 1200.000000 != 1300.046000. CPU Frequency is not max.
    2 1000 7.79 7.40 3.879797

    Keep in mind that our IB bottleneck is our 40Gbe IB Switch. Here is what we can interpret from our test data.

    • Plateau was about: 3776.9 MiB/s which is about 31.7 Gbit/s
    • That is a normal practical result for a nominal 40 Gb InfiniBand-class link
    • Our plateau is consistent and stable, which is good

    Our InfiniBand link is healthy enough to sustain near-expected throughput, there are no obvious severe bottleneck or broken configuration. We are seeing some GPU frequency warnings, and some “PCIe relaxed ordering” warnings so lets fix those any try the test again.

    What is PCIe Relaxed Ordering? PCIe Relaxed Ordering is a performance feature where The CPU/NIC is allowed to reorder memory transactions. This can improve throughput by reducing stalls and increasing parallelism

    On both hosts, run the command below.

    cpupower frequency-set -g performance


    Now back on the first host, kick off the listen side of the test.

    ib_send_bw -d mlx5_0 -i 1 -a -q 4 --disable_pcie_relaxed

    And on the other server we kick off the test itself.

    ib_send_bw -d mlx5_0 -i 1 -a -q 4 --disable_pcie_relaxed <columbia_ip>

    Why these flags

    FlagPurpose
    -d mlx5_0Select your ConnectX-4 device
    -i 1Use IB port 1
    -aSweep all message sizes
    -q 4Use multiple queue pairs (better utilization)
    --disable_pcie_relaxedMatch your CPU capabilities and remove warning

    So lets summarize our output.

    • Almost identical throughput as initial test
    • Slight improvement in consistency
    • Cleaner test conditions (set cpu-frequency to performance)
    • Multiple QPs established (we see 4 QPNs)
    • We still see CPU Frequency is not max, however this is non issue as we have already saturated our links.


    Wrap Up

    In our previous post, we stood up our IB network, and performed some basic fabric tests. Today was all about performance testing and testing with the actual RDMA verb stack. We found that our fabric was pretty much performing as expected out of the box with minimal tuning, as we are hitting near-theoretical limits for our 40Gb hardware.

    We have a stable, low latency, high bandwidth IB Fabric.

    I was hoping to get to GPU direct testing today, however that looks like it might a bit of a beast and I think I will call it a day and do a bit more research on the topic.

  • Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 2: Infiniband Setup

    Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 2: Infiniband Setup
    Black silhouette of a cat with an arched back.

    Part 1: Of this Project Log can be found here

    Now that the 3x Mellanox MCX455A-ECAT ConnectX-4 Adapters have arrived, its time to install them into their respective servers (columbia.lab, prometheus.lab, and viper.lab)


    Verify Mellanox CX4s are Detected

    Once installed, log into the IDRAC of each host and verify that the CX-4 appears in system inventory. Sample output below from one of the hosts.

    Note that you may need to boot the system for the CX-4 to appear in the IDRAC inventory (as Collect System Inventory on Restart” (CSIOR) will run when starting up)

    InfiniBand.Slot.1-1 - PCI Device
    BusNumber 129
    DataBusWidth 16x or x16
    Description ConnectX-4 VPI IB EDR/100 GbE Single Port QSFP28 Adapter
    Device Type PCIDevice
    DeviceDescription InfiniBand.Slot.1-1
    DeviceNumber 0
    FQDD InfiniBand.Slot.1-1
    FunctionNumber 0
    InstanceID InfiniBand.Slot.1-1
    LastSystemInventoryTime 2026-03-14T22:33:28
    LastUpdateTime 2026-03-15T03:33:07
    Manufacturer Mellanox Technologies
    PCIDeviceID 1013
    PCISubDeviceID 0033
    PCISubVendorID 15B3
    PCIVendorID 15B3
    SlotLength Long Length
    SlotType PCI Express Gen 3

    Once each machine has booted to the running OS, you can confirm that the RHEL properly detects the CX-4 with lspci

    lspci | grep -i mel
    44:00.0 Infiniband controller: Mellanox Technologies MT27700 Family [ConnectX-4]

    Verify Numa Topology Via nvidia-smi

    Ideally, for best performance, your GPUS and InfiniBand adapters will be NUMA local to each other. If you were deploying a similar setup in a production environment, NUMA alignment would be critical.

    Our lab setup is less than ideal due to the limited number of PCI slots. In many Dell servers, PCIe risers for GPUs have only one PCIe slot. Stick two of these risers in a single server, and you end up with only 3 slots free on riser 1 (half lenght) which is where we had to install our CX-4s.

    All this being said, we “should” be fine for functional testing. Lets review each of our 3 nodes below. Since NVIDIA Drivers are already installed on all three systems, we can run nvidia-smi and confirm that the CX-4 is in the output and review the topology


    Nvidia-smi output on host viper.lab

    This server viper.lab is a Dell R720 running RHEL 9, and has 2x Nvidia Telsa P4 GPUs installed along with the CX-4.

    nvidia-smi topo -m
    GPU0 GPU1 NIC0 CPU Affinity NUMA Affinity GPU NUMA ID
    GPU0 X PHB SYS 0,2,4,6,8,10 0 N/A
    GPU1 PHB X SYS 0,2,4,6,8,10 0 N/A
    NIC0 SYS SYS X

    In the output above. Both GPUs are local to NUMA node 0 and connected to each other through a PCIe host bridge (PHB), while the ConnectX NIC (mlx5_0) is topologically remote from both GPUs (SYS), making the setup workable but not ideal for GPUDirect RDMA performance. This should be ok for our lab as we are performing functional tests, and performance is secondary. Time will tell.

    Nvidia SMI output on host columbia.lab

    Columbia.lab is a Dell R730, with 1x Nvidia Telsa T4 installed along with one CX-4 (possible to move to another slot, if we had the full length bracket for the CX-4, or had half-length brackets for our NICs on Riser 2.

    nvidia-smi topo -m
    GPU0 NIC0 CPU Affinity NUMA Affinity GPU NUMA ID
    GPU0 X SYS 0,2,4,6,8,10 0 N/A
    NIC0 SYS X

    In the output above, we can see that this system has one GPU (T4) on NUMA node 0 and and CX-4, but the GPU-to-NIC path is SYS, indicating a topologically distant connection that is usable but sub-optimal for GPUDirect RDMA performance. Again, may be fine for functional testing.

    Nvidia SMI output on host prometheus.lab

    This Dell R730 has 2x NVIDIA Tesla T4s installed, as well as the recently installed CX-4

    nvidia-smi topo -m
    GPU0 GPU1 NIC0 CPU Affinity NUMA Affinity GPU NUMA ID
    GPU0 X PHB SYS 0,2,4,6,8,10 0 N/A
    GPU1 PHB X SYS 0,2,4,6,8,10 0 N/A
    NIC0 SYS SYS X

    This output shows two GPUs on the same NUMA node with a moderate GPU-to-GPU path (PHB) and relatively distant NIC connectivity (SYS), which is acceptable for many workloads but not ideal for high-performance GPU-to-NIC or GPUDirect-style traffic.


    Verify Drivers Loaded Properly

    In the first step we saw the CX-4 in the IDRAC, and in the output of lspci. We will now check that the driver has loaded properly. Rinse and repeat on each host.

    lsmod | egrep 'mlx5_core|mlx5_ib|ib_core'
    mlx5_ib 561152 0
    macsec 73728 1 mlx5_ib
    mlx5_core 3153920 2 mlx5_fwctl,mlx5_ib
    mlxfw 49152 1 mlx5_core
    psample 20480 1 mlx5_core
    tls 159744 2 bonding,mlx5_core
    pci_hyperv_intf 12288 1 mlx5_core
    ib_uverbs 217088 2 rdma_ucm,mlx5_ib
    ib_core 573440 12 rdma_cm,ib_ipoib,rpcrdma,ib_srpt,iw_cm,ib_iser,ib_umad,ib_isert,rdma_ucm,ib_uverbs,mlx5_ib,ib_cm

    Lets review the imporant/relevant output below

    mlx5_ib 561152 0
    mlx5_core 3153920 2 mlx5_fwctl,mlx5_ib
    ib_uverbs 217088 2 rdma_ucm,mlx5_ib
    ib_core 573440 12 ...
    • mlx5_core – main low-level kernel driver for Mellanox/NVIDIA ConnectX-4/5-class adapters.
      • the kernel sees the adapter family and has loaded the base driver
      • this is required for the card to function at all
      • other Mellanox modules are depending on it
    • mlx5_ib – This is the InfiniBand/RDMA driver layer for mlx5 devices.
      • the adapter is not just using the generic Ethernet driver path
      • the system has the RDMA / InfiniBand-capable driver loaded
      • the kernel is prepared to expose the card as an IB/RDMA device
    • ib_core – the core InfiniBand subsystem in the kernel.
      • the Linux IB stack is loaded
      • multiple RDMA/IB-related modules are attached to it
      • the host is set up for InfiniBand/RDMA functionality, not just plain NIC support
    • ib_uverbs – This is the userspace verbs interface.
      • userspace RDMA tools and libraries should be able to talk to the device
      • commands like ibv_devinfo, ibstat, and RDMA applications have the proper kernel interface available

    Show Devices and Port State

    First we need to install some prerequesits

    sudo dnf install rdma-core infiniband-diags libibverbs-utils -y

    ibv_devices

    We can show InfiniBand devices with ibv_devices, which shows local RDMA/InfiniBand devices that the OS can see on that host. It does not enumerate remote hosts, switches, or the rest of the IB fabric.

    We will run this command on each host and capture the output.

    On columbia.lab

    [root@columbia ~]# ibv_devices
    device node GUID
    ------ ----------------
    mlx5_0 248a070300ac5414

    On viper.lab

    root@viper:~# ibv_devices
    device node GUID
    ------ ----------------
    mlx5_0 248a070300ac5f6c

    On prometheus.lab

    [root@prometheus ~]$ ibv_devices
    device node GUID
    ------ ----------------
    mlx5_0 248a070300ac5610
    [root@prometheus ~]$

    ibstat

    Now that we have confirmed all devices are present and accounted for lets check for links. In the output below you can see that we have link “Physical state: LinkUp“, but since we have not configured subnet manager on any of our nodes, the logical fabric is “State: Initializing“.

    ibstat
    CA 'mlx5_0'
    CA type: MT4115
    Number of ports: 1
    Firmware version: 12.28.4512
    Hardware version: 0
    Node GUID: 0x248a070300ac5610
    System image GUID: 0x248a070300ac5610
    Port 1:
    State: Initializing
    Physical state: LinkUp
    Rate: 40
    Base lid: 65535
    LMC: 0
    SM lid: 0
    Capability mask: 0x2659e848
    Port GUID: 0x248a070300ac5610
    Link layer: InfiniBand

    Run ibstat on any of your remaining nodes. Ensure that you see “Physical state: LinkUp”. You may also want to make notes of “Firmware version: 12.28.4512“. We have the same firmware on all three CX-4s.


    ibv_definfo

    We can also run ibv_devinfo, which gives a detailed view of the local RDMA / InfiniBand device and its ports. It is more detailed than ibv_devices and overlaps somewhat with ibstat, but from the verbs / RDMA stack perspective.

    Example output below:

     ibv_devinfo
    hca_id:	mlx5_0
    	transport:			InfiniBand (0)
    	fw_ver:				12.28.4512
    	node_guid:			248a:0703:00ac:5414
    	sys_image_guid:			248a:0703:00ac:5414
    	vendor_id:			0x02c9
    	vendor_part_id:			4115
    	hw_ver:				0x0
    	board_id:			DEL2180110032
    	phys_port_cnt:			1
    		port:	1
    			state:			PORT_INIT (2)
    			max_mtu:		4096 (5)
    			active_mtu:		4096 (5)
    			sm_lid:			0
    			port_lid:		65535
    			port_lmc:		0x00
    			link_layer:		InfiniBand
    
    

    This output shows us the following…

    • Local RDMA devices
      • Example: mlx5_0, mlx5_1
    • Port state
      • Example: PORT_ACTIVE, PORT_DOWN, PORT_INIT
    • Physical link state
      • Example: LINK_UP, POLLING, DISABLED
    • Negotiated link details
      • Speed and link width
    • Fabric info
      • Local LID and SM LID
    • Device identifiers
      • Node GUID, port GUID, system image GUID
    • Transport / firmware details
      • Transport type and device-specific details
    • RDMA capabilities
      • Limits such as QPs, CQs, MR size, atomic support, GID table size

    rdma link

    The current output of “rdma link” shows use that our InfiniBand ports are connected but as we know the fabric is not initialized.

    rdma link
    link mlx5_0/1 subnet_prefix fe80:0000:0000:0000 lid 65535 sm_lid 0 lmc 0 state INIT physical_state LINK_UP

    Specifically the output shows us the following.

    • mlx5_0/1
      • Device mlx5_0, port 1
    • subnet_prefix fe80:0000:0000:0000
      • Normal default InfiniBand subnet prefix
    • lid 65535
      • The port does not have a valid assigned LID yet
    • sm_lid 0
      • No subnet manager is detected
    • lmc 0
      • LID mask control is 0; not important here
    • state INIT
      • The port is not fully active yet
    • physical_state LINK_UP
      • The physical link is up and the cable/port side is working

    Setup Subnet Manager on one Host

    For our lab, we are going to only setup subnet manager on one host. Pick your always-on host. Multiple instances of subnet manager can be used, but again, not needed for our current objective.

    On the selected host run the following to install required packages.

     dnf install -y rdma-core opensm infiniband-diags

    Next, start and enable the service

    sudo systemctl enable --now opensm

    Then check to ensure that the service started without error.

    sudo systemctl status opensm --no-pager
    journalctl -u opensm -b --no-pager

    Now we can re-check the fabric on each host. Now we see the Fabric status is “State: Active”

     ibstat
    CA 'mlx5_0'
    	CA type: MT4115
    	Number of ports: 1
    	Firmware version: 12.28.4512
    	Hardware version: 0
    	Node GUID: 0x248a070300ac5f6c
    	System image GUID: 0x248a070300ac5f6c
    	Port 1:
    		State: Active
    		Physical state: LinkUp
    		Rate: 40
    		Base lid: 4
    		LMC: 0
    		SM lid: 1
    		Capability mask: 0x2659e848
    		Port GUID: 0x248a070300ac5f6c
    		Link layer: InfiniBand
    root@viper:~# 
    
    

    rdma link shows similar output.

    rdma link
    link mlx5_0/1 subnet_prefix fe80:0000:0000:0000 lid 4 sm_lid 1 lmc 0 state ACTIVE physical_state LINK_UP

    Confirm Infiniband Fabric Topology

    You can run the following commands to confirm that your fabric is up and running

    Run the “ibnetdiscover” to see host adapters, links, GUIDs, port relationships, and switches. Example output below

    ibnetdiscover
    #
    # Topology file: generated on Sat Mar 14 21:15:43 2026
    #
    # Initiated from node 248a070300ac5f6c port 248a070300ac5f6c
    vendid=0x2c9
    devid=0xbd36
    sysimgguid=0x2c902004cf11b
    switchguid=0x2c902004cf118(2c902004cf118)
    Switch 8 "S-0002c902004cf118" # "Infiniscale-IV Mellanox Technologies" base port 0 lid 3 lmc 0
    [1] "H-248a070300ac5f6c"[1](248a070300ac5f6c) # "viper mlx5_0" lid 4 4xQDR
    [2] "H-248a070300ac5414"[1](248a070300ac5414) # "columbia mlx5_0" lid 1 4xQDR
    [3] "H-248a070300ac5610"[1](248a070300ac5610) # "prometheus mlx5_0" lid 2 4xQDR
    vendid=0x2c9
    devid=0x1013
    sysimgguid=0x248a070300ac5414
    caguid=0x248a070300ac5414
    Ca 1 "H-248a070300ac5414" # "columbia mlx5_0"
    [1](248a070300ac5414) "S-0002c902004cf118"[2] # lid 1 lmc 0 "Infiniscale-IV Mellanox Technologies" lid 3 4xQDR
    vendid=0x2c9
    devid=0x1013
    sysimgguid=0x248a070300ac5610
    caguid=0x248a070300ac5610
    Ca 1 "H-248a070300ac5610" # "prometheus mlx5_0"
    [1](248a070300ac5610) "S-0002c902004cf118"[3] # lid 2 lmc 0 "Infiniscale-IV Mellanox Technologies" lid 3 4xQDR
    vendid=0x2c9
    devid=0x1013
    sysimgguid=0x248a070300ac5f6c
    caguid=0x248a070300ac5f6c
    Ca 1 "H-248a070300ac5f6c" # "viper mlx5_0"
    [1](248a070300ac5f6c) "S-0002c902004cf118"[1] # lid 4 lmc 0 "Infiniscale-IV Mellanox Technologies" lid 3 4xQDR

    In the output above we can see the following

    • One Mellanox InfiniScale-IV switch is present in the fabric
      • Switch GUID: 0x2c902004cf118
      • Switch LID: 3
      • Model family shown as Infiniscale-IV Mellanox Technologies
      • It is an 8-port switch
    • Three hosts are connected to the switch
      • columbia on switch port 2, LID 1
      • prometheus on switch port 3, LID 2
      • viper on switch port 1, LID 4
    • All three hosts are being seen as CA / HCA nodes
      • columbia mlx5_0
      • prometheus mlx5_0
      • viper mlx5_0
    • All discovered links are running at:
      • 4xQDR
      • That means a 4-lane QDR InfiniBand link, which aligns with a 40 Gb/s class IB link

    This output confirms that OpenSM is working properly, that the switch is visible, and all three nodes are connected to the fabric.

    Run “ibnodes” which provides a similar output to ibdiscover, albeit a bit less verbose.

    ibnodes
    Ca : 0x248a070300ac5610 ports 1 "prometheus mlx5_0"
    Ca : 0x248a070300ac5414 ports 1 "columbia mlx5_0"
    Ca : 0x248a070300ac5f6c ports 1 "viper mlx5_0"
    Switch : 0x0002c902004cf118 ports 8 "Infiniscale-IV Mellanox Technologies" base port 0 lid 3 lmc 0

    Run “ibswitches” to see switches only.

     ibswitches
    Switch	: 0x0002c902004cf118 ports 8 "Infiniscale-IV Mellanox Technologies" base port 0 lid 3 lmc 0
    
    

    iblinkinfo will show you InfiniBand topology info

     iblinkinfo
    CA: viper mlx5_0:
          0x248a070300ac5f6c      4    1[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       3    1[  ] "Infiniscale-IV Mellanox Technologies" ( )
    CA: columbia mlx5_0:
          0x248a070300ac5414      1    1[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       3    2[  ] "Infiniscale-IV Mellanox Technologies" ( )
    Switch: 0x0002c902004cf118 Infiniscale-IV Mellanox Technologies:
               3    1[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       4    1[  ] "viper mlx5_0" ( )
               3    2[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       1    1[  ] "columbia mlx5_0" ( )
               3    3[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       2    1[  ] "prometheus mlx5_0" ( )
               3    4[  ] ==(                Down/ Polling)==>             [  ] "" ( )
               3    5[  ] ==(                Down/ Polling)==>             [  ] "" ( )
               3    6[  ] ==(                Down/ Polling)==>             [  ] "" ( )
               3    7[  ] ==(                Down/ Polling)==>             [  ] "" ( )
               3    8[  ] ==(                Down/ Polling)==>             [  ] "" ( )
    CA: prometheus mlx5_0:
          0x248a070300ac5610      2    1[  ] ==( 4X          10.0 Gbps Active/  LinkUp)==>       3    3[  ] "Infiniscale-IV Mellanox Technologies" ( )
    
    

    In the output above, we see …

    • 4x 10Gbps per lane
    • InfiniBand speed class is QDR
    • aggregate raw signaling rate is about 40 Gb/s
    • Down/Polling – unused/not-connected switch ports

    And finally, “sminfo” will show you info on subnet manager.

    Specifically (below) we see that subnet manager is reachable on LID1, with a GUID of 0x248a070300ac5414 (which belongs to columbia mlx5_0). We also see “activity count 446” which shows that subnet manager has processed fabric-management activity 466 times since startup (basically a liveness/activty counter).

    Additionally the output below show us the priority of the subnet manager instance (0 in this case), while state 3 SMINFO_MASTER shows us that this instance of subnet manager is in the master state and is the active controller in our IB fabric (assigning LIDS, managing paths/routing)

    sminfo
    sminfo: sm lid 1 sm guid 0x248a070300ac5414, activity count 446 priority 0 state 3 SMINFO_MASTER

    Configuring IP over InfiniBand

    IP over InfiniBand, or IPoIB, allows an InfiniBand fabric to carry normal IP traffic between hosts. That means systems connected by InfiniBand can use familiar network tools and services such as ping, ssh, scp, NFS, and other TCP/IP-based applications over the IB link instead of only using native RDMA-aware software.

    IPoIB is not required for RDMA itself, and it is also not inherently required for technologies like GPUDirect RDMA. RDMA and GPUDirect RDMA operate through the RDMA/verbs stack and the InfiniBand fabric, not through the IP emulation layer that IPoIB provides. NVIDIA’s current networking/operator docs describe RDMA and GPUDirect RDMA enablement separately from IPoIB, and they also document IPoIB as an optional deployment pattern rather than a prerequisite.

    We use IPoIB when we want the simplicity of standard IP networking on top of the higher-speed, low-latency InfiniBand fabric. In a small lab or cluster, this is useful for private host-to-host traffic, storage traffic, migration traffic, testing, or other east-west communication, while leaving the normal Ethernet interfaces in place for management access, internet access, and general connectivity.

    IPoIB Addresses for our lab

    Our lab uses 10.1.x.x for its existing IP scheme, so to avoid any confusion, we will use 172.16.x.x addresses for our small private subnet on the IB network. Note that we do not need a gateway.

    HOSTIPoIB AddressINTERFACE
    prometheus.lab172.16.50.11/24ibp129s0
    columbia.lab172.16.50.12/24ibp129s0
    viper.lab172.16.50.13/24ibp68s0

    As part of our initial temporary test, we will apply the IPoIB addresses to the indicated interfaces on each host (all as outlined above. Example temporary config will be for one host. However we will run the command (modified) for each host in our cluster.

    sudo ip link set ibp129s0 up
    sudo ip addr add 172.16.50.11/24 dev ibp129s0

    As you go host to host, verify that the address was assigned correctly.

    9: ibp129s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2044 qdisc mq state UP group default qlen 1000
    link/infiniband 00:00:03:f2:fe:80:00:00:00:00:00:00:24:8a:07:03:00:ac:56:10 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    inet 172.16.50.11/24 scope global ibp129s0
    valid_lft forever preferred_lft forever

    Also verify your routing table.

     netstat -rn
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
    0.0.0.0         10.1.10.1       0.0.0.0         UG        0 0          0 bridge0
    10.1.10.0       0.0.0.0         255.255.255.0   U         0 0          0 bridge0
    169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 idrac
    172.16.50.0     0.0.0.0         255.255.255.0   U         0 0          0 ibp129s0
    
    

    Now perform ping tests from each host and ensure that they can hit the remaining hosts in your cluster. For example.

    ping -I ibp129s0 -c 2 172.16.50.12
    ping -I ibp129s0 -c 2 172.16.50.13

    Once you have tested all three hosts, we can move forward with configuring persistent network configs.


    Persistent RHEL 10 / NetworkManager setup

    prometheus.lab

    sudo nmcli connection add type infiniband ifname ibp129s0 con-name ib-ibp129s0
    sudo nmcli connection modify ib-ibp129s0 ipv4.method manual ipv4.addresses 172.16.50.11/24 ipv6.method disabled
    sudo nmcli connection up ib-ibp129s0
    
    
    
    
    

    columbia.lab

    sudo nmcli connection add type infiniband ifname ibp129s0 con-name ib-ibp129s0
    sudo nmcli connection modify ib-ibp129s0 ipv4.method manual ipv4.addresses 172.16.50.12/24 ipv6.method disabled
    sudo nmcli connection up ib-ibp129s0

    viper.lab

    sudo nmcli connection add type infiniband ifname ibp68s0 con-name ib-ibp68s0
    sudo nmcli connection modify ib-ibp68s0 ipv4.method manual ipv4.addresses 172.16.50.13/24 ipv6.method disabled
    sudo nmcli connection up ib-ibp68s0

    Confirm Routing

    Use “ip route” to ensure that we have the proper route in place for our IPoIB network

    ip route
    default via 10.1.10.1 dev bridge0 proto static metric 425
    10.1.10.0/24 dev bridge0 proto kernel scope link src 10.1.10.25 metric 425
    169.254.0.0/16 dev idrac proto kernel scope link src 169.254.0.2 metric 100
    172.16.50.0/24 dev ibp68s0 proto kernel scope link src 172.16.50.13 metric 150

    Also confirm that NetworkManger sees our IB devices correctly (as Infiniband)

    nmcli device status
    DEVICE TYPE STATE CONNECTION
    bridge0 bridge connected bridge0
    idrac ethernet connected idrac
    ibp68s0 infiniband connected ib-ibp68s0
    bond0 bond connected bond0
    enp65s0f0 ethernet connected bond0-port0
    enp65s0f1 ethernet connected bond0-port1
    
    
    
    
    

    IP, IPoIB, and RDMA Usage Matrix

    We can use this simple decision matrix to ensure that we understand when to use traditional IP for host to host communication, vs when to use IPoIB, and when native RDMA/IB

    Use caseEthernetIPoIBNative RDMA / IB
    Host management, SSH, web UI, package installsBest choicePossible, but usually unnecessaryNo
    Internet access / default routeBest choiceNoNo
    General admin traffic between hostsBest choiceGood for isolated lab trafficNo
    Simple host-to-host testing with ping, ssh, scp, rsync over IB fabricNoBest choiceNo
    NFS/SMB using normal IP networking over the IB fabricNoBest choiceNo
    Fast private storage or migration traffic using standard TCP/IP appsNoBest choiceNo
    RDMA-aware apps using verbs/libibverbsNoNoBest choice
    MPI or cluster workloads built for native IB/RDMANoSometimes, if app specifically uses IPBest choice
    GPUDirect RDMA / high-performance GPU-to-network workflowsNoNoBest choice
    Lowest latency / highest efficiency IB data pathNoNoBest choice
    Easiest troubleshooting and least risk of routing mistakesBest choiceGood if kept isolatedMore specialized

    Next Steps.

    So in Part 2 of our project, we focused on getting InfiniBand up and running, as well as IPoIB. We validated connectivity and setup subnet manager and made sure that our fabric was initialized. We leared a number of IB related command and learned how to read their output. Good Stuff.

    In our next post we will start working with the various NVIDIA tools and projects, many of which will rely on our IB network. Additionally we may try to update firmware on our CX-4s and our IB Switch, however I may skip this step or circle back to it later.

  • Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 1: Project Overview

    Project “NVIDIA HPC Infiniband Homelab GPU Cluster”: Part 1: Project Overview

    Introduction

    InfiniBand is a mature interconnect technology known for high bandwidth and low latency. It has long been used in supercomputing and HPC environments, and has also been deployed in certain storage and clustered infrastructure designs as an alternative to Fibre Channel.

    More recently, InfiniBand has seen strong continued adoption in large-scale AI and GPU clusters, where its high bandwidth, ultra-low latency, and support for technologies such as RDMA, GPUDirect RDMA, and NCCL make it well suited for distributed training and other GPU-to-GPU communication workloads.

    This project involves the architecture, deployment, and optimization of a high-speed InfiniBand (IB) fabric to facilitate low-latency, high-throughput communication between 3x dual-homed, GPU enabled, RHEL 9/10.1 servers.

    By integrating Mellanox ConnectX-4 adapters with an InfiniScale IV switch, we will establish a dedicated Remote Direct Memory Access (RDMA) backend separate from the standard management LAN.

    Additionally, we will become more familiar with the setup, configuration, and troubleshooting of InfiniBand networks and adapters, while also exploring the broad set of NVIDIA tools and technologies currently available to support multi-GPU clusters.

    This project also encompasses the installation and configuration of NVIDIA drivers, CUDA, the NVIDIA Container Toolkit, and other supported elements of the NVIDIA software stack needed to support HCP/AI Clusters and environments.

    Primary Objectives Summary

    • Fabric orchestration: Deploy and manage a QDR InfiniBand fabric using OpenSM.
    • RDMA enablement: Configure IPoIB in Connected Mode with a 65,520 MTU and validate RDMA functionality across the fabric.
    • GPU acceleration: Enable and test GPUDirect RDMA with nvidia-peermem for NVIDIA Tesla T4 and P4 GPUs.
    • Platform enablement: Install and configure NVIDIA drivers, CUDA, the NVIDIA Container Toolkit, and other supported NVIDIA software stack components required for GPU-enabled workloads.
    • Operations and telemetry: Develop hands-on familiarity with InfiniBand diagnostics, troubleshooting, and NVIDIA GPU monitoring tools.

    Bill of Materials (BOM)

    Below is the BOM for this project.

    ComponentQtyPARTDESCRIPTION
    Switch1xMellanox InfiniScale IV Is5022 Switch8-port Non-blocking Unmanaged 40Gb/s InfiniBand Switch System
    NICs3xMCX455A-ECAT MELLANOX CONNECTX-4 1 PORT EDR 100GB IB QSFP28 Infiniband/Ethernet Adapter
    GPU (New)2xNVIDIA Tesla P4 8GB GDDR5 (with active cooling mods) 
    GPU (Existing)3xNVIDIA Tesla T4 16GB GDDR5 (with active cooling mods) 
    Cabling3xFS 40Gbps QSFP+ 2M Passive DAC (QSFP-PC02) 3x Host to 1x Switch
    Server1xDell R720 (RHEL 9)2 x Intel Xeon E5-2697 (Ivy Bridge) v2 Twelve-Core Processor 2.7GHz 8.0GT/s 30MB LGA 2011, 128GB
    Server1xDell R730 (RHEL 10.1)2x Intel(R) Xeon(R) CPU E5-2690 (Broadwell-EP) v4 @ 2.40GHz, 256GB
    Server 1xDell R730 (RHEL 10.1)2x Intel® Xeon® Processor E5-2699 v4 (Broadwell-EP) @2.20GHz, 768GB

    Notes On the Bill of Materials (BOM)

    There as been a bit of flux on the exact BOM for this project (and my lab). A Dell R720 was recently added to my lab, replacing a mammoth T620. And while I like the tower form factor due to its ample number of PCI slots and spare SATA power cables, it has to sit on a rack mount shelf, takes up 5RU and is really heavy amd hard to move.

    So the CPUs/Memory from the T620 were migrated to the R720. However RHEL 10 deprecated support for Intel v2 processors, so I had to deploy RHEL 9 instead of RHEL10. RHEL 9 supported the CX-3 with in-band drivers, however support for the CX-3 was dropped from RHEL 10. So I had to switch to CX-4s, which were more costly. However further research found that RDMA was not supported on the CX-3, so I needed to move to the CX4 (or newer) anyways.

    IB Switch – I was able to pick up the unmanaged Mellanox InfiniScale switch on eBay quite cheaply. Being unmanaged it does not run subnet manager, which I will need to run on my primary host. Limited to 40GBe per port.

    IB Adapters – Initially, as stated above, I intended to use Mellanox CX-3 adapters as they were incredibly inexpensive (like $12 USD), however due to CX-3 driver being dropped in RHEL 10, I switched to CX-4s, which were supported out of the box on both RHEL 9 and RHEL 10. These adapters were not as cheap, but still affordable. Additionally, I needed low profile brackets in order to fit into the existing open PCIe slots in my servers. I did not want to use OFED drivers, as I was looking to have the adapters supported out of the box, and was not interested in fiddling with drivers. Additionally, support docs for RDMA mentioned CX-4 or newer were required.

    GPUS – Workstation class GPUs (like my 1x 3070 and my 2x 3060s 12Gb are not supported. I needed Datacenter Class NVIDIA CPUs installed in all 3 Dell Servers. I already owned 3x NVIDIA Tesla T4 (installed in R730s). Picked up 2x additional GPUs (NVIDIA Tesla M4), which are for functional validation only – not purchased for their performance or VRAM. Additional requirement was to stick with low-power GPUs that ran on PCIe power alone and did not require additional power connections.


    Nvidia T4/P4 Comparison and Feature Support

    Our LUT (Lab Under Test) consists of 5 GPUs, deployed across 3 Servers. Details below

    FeatureNVIDIA T4NVIDIA Tesla P4
    ArchitectureTuringPascal
    Release dateSeptember 12, 2018September 12, 2016
    CUDA cores2,5602,560
    Tensor cores320None
    vRAM16 GB GDDR68 GB GDDR5
    Memory bandwidth300–320+ GB/s192 GB/s
    PCIe interfacePCIe Gen3 x16PCIe Gen3
    Form factorLow-profile, single-slot, passiveLow-profile, single-slot, passive
    Max power70 W75 W
    ECC memory supportYesYes
    NVENC / NVDECYesYes
    NVIDIA vGPU supportYesYes
    GPUDirect RDMAYes, conditionally supportedYes, conditionally supported
    RDMA NIC requirementConnectX-4 or laterConnectX-4 or later
    GPUDirect RDMA topology requirementGPU and NIC should share the same upstream PCIe root complex for best support/performanceGPU and NIC should share the same upstream PCIe root complex for best support/performance
    NVLinkNoNo
    MIGNoNo

    Additional GPUs Available

    In addition to the 5x GPUs currently installed in my existing lab servers, I have few additional GPUs that are not currently deployed. I will include them below for reference.

    Generally speaking, these are either “older“, “hungrier” or “hotter” than the GPUs that I already have in service.

    FeatureNVIDIA Tesla K20NVIDIA Tesla P100
    ArchitectureKeplerPascal
    Release dateNovember 2012April 5, 2016
    CUDA cores2,4963,584
    Tensor coresNoneNone
    vRAM5 GB GDDR516 GB HBM2
    Memory bandwidth208 GB/s732 GB/s
    PCIe interfacePCIe Gen2 x16PCIe Gen3 x16
    Form factorFull-height, dual-slotFull-height, dual-slot
    Max power225 W250 W
    ECC memory supportYesYes
    NVENC / NVDECNoNo
    NVIDIA vGPU supportNoYes
    GPUDirect RDMAYes, conditionally supportedYes, conditionally supported
    RDMA NIC requirementConnectX-4 or laterConnectX-4 or later
    GPUDirect RDMA topology requirementGPU and NIC should share the same upstream PCIe root complex for best support/performanceGPU and NIC should share the same upstream PCIe root complex for best support/performance
    NVLinkNoDepends on model; PCIe P100: No, SXM2 P100: Yes
    MIGNoNo

    NVIDIA Tool Test Matrix

    Below is a Matrix of technologies, their supportability in my soon to be deployed stack, and a brief description of each technology.

    Technology / ProductSupportedDescriptionPriorityNOTES
    RDMA (InfiniBand / verbs)SupportedRemote Direct Memory Access. It is a networking technology that lets one computer access or transfer data directly to the memory of another computer without involving the remote CPU or operating system in the data path.
    HighDirect memory access over the network using your ConnectX-4 InfiniBand cards. This is the base networking capability you will use for low-latency, high-throughput node-to-node transfers.

    Native fit for CX-4 + IB switch
    GPUDirect RDMASupported GPUDirect RDMA is an NVIDIA technology that lets a third-party PCIe device directly read from or write to GPU memory without first copying the data through system RAM.HighLets a supported NIC perform RDMA directly to/from GPU memory, bypassing extra CPU copies. NVIDIA documents GPUDirect RDMA for Tesla/Quadro GPUs and requires ConnectX-4 or later NICs, with best results when GPU and NIC share the same upstream PCIe root complex. (NVIDIA Docs)

    One of the most relevant GPU+IB features for this setup
    GPUDirect StorageUnclearDesigned for direct data movement between storage and GPU memory. It is primarily positioned around storage stacks rather than IB switching alone, so whether your exact lab can validate it depends on OS, filesystem, NVMe/storage path, and supported software stack rather than just T4/P4 + CX-4. (NVIDIA Docs)Low NVIDIA technology that allows data to move directly between storage and GPU memory using DMA, instead of first bouncing through CPU memory.

    Best with NVME storage, have only SSDs and HDDs, no NVME support in Dell models under test.
    MIG (Multi-Instance GPU)Not supportedMIG starts with newer architectures and is documented in NVIDIA’s MIG guide as an Ampere-era feature. NVIDIA’s cloud-native docs explicitly note that Tesla T4 does not support MIG. P4 also predates MIG. (NVIDIA Docs)NoneNot supported.

    Multi-Instance GPU. It is an NVIDIA technology that lets a single supported GPU be partitioned into multiple smaller, isolated GPU instances
    Time-slicing / shared GPU schedulingSupportedGood for shared-lab/VM experiments
    Allows multiple workloads share one physical GPU by giving each workload a small turn on the GPU scheduler
    MediumSince T4 does not support MIG, NVIDIA documents time-slicing as a way to share T4 across multiple smaller jobs. This is useful for Kubernetes/OpenShift experiments or general shared-lab validation. P4 can also be shared through virtualization/software scheduling rather than MIG. (NVIDIA Docs)
    NVIDIA vGPUSupportedNVIDIA’s virtual GPU stack allows partitioning/sharing GPUs across VMs for compute, VDI, or graphics use cases. Both T4 and P4 are in NVIDIA’s supported vGPU product documentation. (NVIDIA Docs)HighNVIDIA’s docs describe it as enabling multiple VMs to have simultaneous, direct access to a single physical GPU using NVIDIA drivers inside the guest OS.

    It lets multiple virtual machines share one physical NVIDIA GPU.
    DCGM (Data Center GPU Manager)SupportedNVIDIA’s primary datacenter GPU management and telemetry framework for health, diagnostics, topology, clocks, thermals, ECC, profiling, and integration with cluster tooling. It is explicitly built for Tesla/datacenter GPUs. (NVIDIA Docs)HighDCGM is NVIDIA’s datacenter GPU management and monitoring framework. NVIDIA describes it as a lightweight user-space library/agent for administering NVIDIA datacenter GPUs in clusters and datacenters.
    DCGM ExporterSupportedPrometheus exporter built on top of DCGM that exposes GPU metrics over HTTP for scraping. Good fit for validating telemetry, dashboards, and alerting with your servers. (NVIDIA Docs)HighNVIDIA’s Prometheus exporter for GPU metrics, will utilize existing Grafana instance

    Easy to validate and useful operationally
    NVIDIA MerlinSupportedMerlin is NVIDIA’s recommender-system framework stack for training and especially inference pipelines. T4 is a strong fit; P4 may work for smaller or older inference experiments, but T4 is the more relevant target. Support is practical rather than “card-specific” in docs, since Merlin rides on the CUDA/framework/container stack. (NVIDIA Developer)MediumLowNVIDIA framework for building recommender systems.

    A recommender system is the kind of ML system used for things like:
    product recommendations
    “people also watched”
    next-best content
    ranking search or feed results
    ad / click-through prediction
    TensorRTSupportedTensorRT is NVIDIA’s SDK/runtime for optimizing trained neural-network models for inference on NVIDIA GPUs. It takes a model from frameworks such as TensorFlow, PyTorch, or ONNX and builds an optimized inference engine that can use precision modes such as FP32, FP16, and INT8 where supported.HighNVIDIA’s inference optimizer/runtime. Very relevant for T4 and still usable on P4. T4 benefits significantly from Tensor Cores, so it is the better platform for validation. (NVIDIA Developer)
    CUDASupportedCore GPU programming/runtime stack. Required for most of the technologies you listed and the base layer for custom validation, benchmarks, peer access tests, and GPU-aware applications. (NVIDIA Docs)HighFoundation for most modern NVIDIA workflows
    NVIDIA Container ToolkitSupportedEnables Docker/Podman/Kubernetes containers to access NVIDIA GPUs cleanly. Useful for validating Merlin, TensorRT, PyTorch, RAPIDS, and exporter containers. (NVIDIA Docs)HighFoundation for most modern NVIDIA workflows, integrate with Podman on RHEL
    NVIDIA GPU OperatorSupportedKubernetes/OpenShift operator that automates driver, toolkit, DCGM, exporter, and related GPU software deployment. Best fit if you want to turn a lab into a small cluster validation environment. (NVIDIA Docs)LowGood if you want Kubernetes/OpenShift validation, however no plans to run OCP in near future.
    NVIDIA Fabric ManagerNot supported / not applicableNVIDIA Fabric Manager is software for managing NVSwitch / NVLink GPU fabrics inside supported multi-GPU servers. NVIDIA says it configures the NVSwitch memory fabric to form a single memory fabric among participating GPUs and monitors the NVLinks that support that fabric.NoneFabric Manager is for NVSwitch-based systems, not T4/P4 PCIe accelerator setups. Installed cards do not use NVSwitch. (NVIDIA Docs)

    Not supported here
    NVLinkNot supportedNVLink is NVIDIA’s high-speed direct interconnect for GPUs. It provides a much faster path for GPU-to-GPU communication than ordinary PCIe alone, and in some platforms it is also used for CPU/GPU or switch-based interconnect designs. NVIDIA describes it as a direct GPU-to-GPU interconnect used to scale multi-GPU I/O within a server.NoneNot Supported. Neither T4 nor P4 provides NVLink. Multi-node connectivity would be via InfiniBand/RDMA, not GPU-to-GPU NVLink. (NVIDIA)
    NVIDIA NIM / inference microservicesUnclear / limitedNVIDIA NIM is NVIDIA’s set of prebuilt, optimized, containerized inference microservices for running AI models on NVIDIA GPUs. NVIDIA describes NIM as portable microservices that simplify deployment of AI models across cloud, datacenter, workstation, and edge environments, typically exposing standard APIs for integration into applicationsLowPossible in some cases, but modern NIM profiles often assume newer GPUs and larger memory footprints than P4, and sometimes more than T4 depending on model size. It is worth testing selectively with small models, but I would not assume broad support on P4/T4 without checking the specific NIM/model requirements. (NVIDIA Docs)
    Mixed precision inference / trainingT4: Supported / P4: LimitedMixed precision means using a mix of higher-precision and lower-precision numeric formats in AI workloads so you get better speed and lower memory use without giving up model quality where precision still matters.LowT4 supports Tensor Cores and is much better for FP16/INT8 inference acceleration. P4 lacks Tensor Cores, so mixed-precision benefits are more limited and workload-dependent. (NVIDIA)
    NCCL (multi-GPU collectives)Supported, but topology-dependentNVIDIA Collective Communications Library. It is NVIDIA’s library for fast GPU-to-GPU communication, including both multi-GPU within a server and multi-node across servers. NVIDIA describes it as a topology-aware library of collective communication primitives optimized for NVIDIA GPUs and networking.MediumUseful for experimenting with multi-GPU and possibly multi-node communication patterns. It can work over PCIe and network paths, but the quality of results depends heavily on topology and software stack. This is a practical support judgment rather than a clean per-card matrix in the cited pages. (NVIDIA Docs)

    Is Supported on by both T4/P4
    Single-host NCCL tests across multiple GPUs in one server

    Multi-node NCCL tests over InfiniBand

    GPUDirect RDMA-assisted NCCL when the stack and PCIe topology cooperate


    GPUDirect P2P / peer-to-peerUnclear / topology-dependentGPU peer-to-peer memory access: one NVIDIA GPU can directly access or copy data to another NVIDIA GPU’s memory without staging the transfer through host RAMPeer-to-peer GPU memory access can work in some PCIe topologies, but support and performance vary a lot by motherboard, root complex, ACS/IOMMU behavior, and driver stack. Possibly worth validating experimentally in homelab. (NVIDIA Docs)

    Project Status

    Currently I am in the “waiting for hardware” to arrive stage of the project (mainly due to the switch from CX-3s to CX-4s). So lets take stock of where we are in the project and outline our next steps.

    Current State

    • IB Switch Racked
    • GPUs physically installed in all systems
    • Rough list of supported technologies to install and test
    • Basic installation steps and IB troubleshooting documented

    Next Steps

    • Install all CX-4, ensure drivers are installed/loaded properly, and possibly update CX-4 firmware
    • Install NVIDIA drivers, CUDA, and Container Toolkit on all GPU enabled hardware
    • Install IB cables, and power up the Mellanox IB Switch (and hope its not too loud)
    • Install 1x instance of active Subnet Manager (OpenSM) on one of target hosts
    • Configure IB IPs.
    • Work through listed/supported technologies in the NVIDIA matrix above.

    My goal is to document my progress in future posts.

  • How to Set Up NVIDIA CUDA and Container Toolkits on RHEL 10

    How to Set Up NVIDIA CUDA and Container Toolkits on RHEL 10

    Introduction

    In this step-by-steps guide we will replace the out of the box nouveau drivers on RHEL 10.1 with NVIDIA Drivers. We will also install the the NVIDIA CUDA Toolkit and the Nvidia Container Toolkit.


    What’s New

    For RHEL 10, Red Hat has simplified the driver installation process through the Extensions channel. You might not need nvidia-detect if you use this simplified method, as the RHEL 10 can now handle the detection and installation for you. 

    NVIDIA Driver install via built-in RHEL drivers Command

    Enable the required repos

    # sudo subscription-manager repos --enable=rhel-10-for-x86_64-appstream-rpms
    # sudo subscription-manager repos --enable=rhel-10-for-x86_64-baseos-rpms
    # sudo subscription-manager repos --enable=codeready-builder-for-rhel-10-x86_64-rpms

    Install the rhel-drivers package:
    This package provides the simplified installation utility:

    # sudo dnf install rhel-drivers

    Install NVIDIA drivers:
    Use the rhel-drivers command to automatically install the correct NVIDIA kernel and user-mode drivers:

    # sudo rhel-drivers install nvidia

    Reboot

    Now verify drivers with nvidia-smi command. Below we can see that the driver has loaded properly and my GPU is visible.

    nvidia-smi
    Wed Mar 11 14:39:26 2026
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 580.105.08 Driver Version: 580.105.08 CUDA Version: 13.0 |
    +-----------------------------------------+------------------------+----------------------+
    | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
    | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
    | | | MIG M. |
    |=========================================+========================+======================|
    | 0 Tesla T4 Off | 00000000:04:00.0 Off | 0 |
    | N/A 34C P8 9W / 70W | 0MiB / 15360MiB | 0% Default |
    | | | N/A |
    +-----------------------------------------+------------------------+----------------------+
    +-----------------------------------------------------------------------------------------+
    | Processes: |
    | GPU GI CI PID Type Process name GPU Memory |
    | ID ID Usage |
    |=========================================================================================|
    | No running processes found |
    +-----------------------------------------------------------------------------------------+

    Note that in the output above you can see a mention of CUDA version. This does not mean that CUDA is installed, rather it shows you the maximum CUDA version supported by the currently installed driver.

    NVIDIA-SMI 580.105.08 Driver Version: 580.105.08 CUDA Version: 13.0

    Installing the NVIDIA Cuda Toolkit

    In order to install the CUDA toolkit you must first add the appropriate NVIDIA repo for RHEL 10

    dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel10/x86_64/cuda-rhel10.repo

    Now we can install the toolkit

    sudo dnf install -y cuda-toolkit

    This installs:

    • nvcc
    • cuBLAS
    • cuDNN libraries
    • NCCL
    • profiling tools
    • headers and dev libraries

    Installing the NVIDIA Container Toolkit

    Again we need to add the appropriate repo.

    sudo dnf config-manager --add-repo \
    https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo

    Then install the toolkit.

    sudo dnf install -y nvidia-container-toolkit

    Now we need to configure the nvidia container toolkit to use podman, since that is default in RHEL.

    sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

    This will create “/etc/cdi/nvidia.yaml”

    We can now verify that the toolkit is properly configured to use our local GPU.

    nvidia-ctk cdi list
    INFO[0000] Found 3 CDI devices
    nvidia.com/gpu=0
    nvidia.com/gpu=GPU-836394e6-a996-65fe-346c-dff40777b64b
    nvidia.com/gpu=all

    Now we want to verify our entire stack (Driver, CUDA, Container Toolkit, and Podman) and run nvidia-smi in a container

    podman run --rm --device nvidia.com/gpu=all \
    nvidia/cuda:12.4.1-base-ubi9 nvidia-smi

    We should see podman pull the container, launch the container, and run the nvidia-smi command via the container, the output should reflect the presence of out GPU.

    podman run --rm --device nvidia.com/gpu=all \
    nvidia/cuda:12.4.1-base-ubi9 nvidia-smi
    ✔ docker.io/nvidia/cuda:12.4.1-base-ubi9
    Trying to pull docker.io/nvidia/cuda:12.4.1-base-ubi9...
    Getting image source signatures
    Copying blob 9d63f91420d1 done |
    Copying blob 1153e061da4e done |
    Copying blob 179428f5acc5 done |
    Copying blob 0c5b8a057cc7 done |
    Copying blob 39150e63d9d9 done |
    Copying blob 8f6600363965 done |
    Copying config 3c259000df done |
    Writing manifest to image destination
    Wed Mar 11 18:49:36 2026
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 580.105.08 Driver Version: 580.105.08 CUDA Version: 13.0 |
    +-----------------------------------------+------------------------+----------------------+
    | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
    | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
    | | | MIG M. |
    |=========================================+========================+======================|
    | 0 Tesla T4 Off | 00000000:04:00.0 Off | 0 |
    | N/A 34C P8 9W / 70W | 0MiB / 15360MiB | 0% Default |
    | | | N/A |
    +-----------------------------------------+------------------------+----------------------+
    +-----------------------------------------------------------------------------------------+
    | Processes: |
    | GPU GI CI PID Type Process name GPU Memory |
    | ID ID Usage |
    |=========================================================================================|
    | No running processes found |
    +-----------------------------------------------------------------------------------------+

    Additionally we can verify cuda was installed correctly via the command below.

    # nvcc --version
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2025 NVIDIA Corporation
    Built on Fri_Nov__7_07:23:37_PM_PST_2025
    Cuda compilation tools, release 13.1, V13.1.80
    Build cuda_13.1.r13.1/compiler.36836380_0

    Note if the command above fails, you may need to setup $PATH for your user and/or root. So run the commands below to update $PATH for all users.

    echo 'export PATH=/usr/local/cuda/bin:$PATH' | sudo tee /etc/profile.d/cuda.sh
    echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' | sudo tee -a /etc/profile.d/cuda.sh

    Then source the profile.

    source /etc/profile.d/cuda.sh
  • RHEL 10 – Enable Health Monitoring for NVIDIA GPUs Using DCGM Exporter

    RHEL 10 – Enable Health Monitoring for NVIDIA GPUs Using DCGM Exporter

    Nvidia Datacenter GPU Manager (DCGM) is a suite of tools that provides health monitoring, performance telemetry, and proactive diagnostics for NVIDIA GPUs deployed on bare-metal servers. It is mainly installed for managing a fleet of GPUs across a large number of GPU enabled nodes.

    DCGM does not have a WebUI, and is often seen “exporting” metrics into Grafana or other enterprise observability tools (like Zabbix) via Prometheus Scrape. I have both Grafana and Zabbix in my lab environment so I have a couple of options to where I want to visualize the data.

    In this post, we are going to …

    • Validate GPU Host Setup
    • Install Nvidia DCGM
    • Enable Health Watches via DCGM
    • Setup dcgm-exporter for exporting of GPU metrics

    Nvidia Drivers Install on RHEL 10.1

    A lot has changed in RHEL 10.1 regarding the installation of NVIDIA drivers on RHEL 10. You can now install them via rhel-drivers.

    The post below is pretty throughout on the topic
    https://www.redhat.com/en/blog/introducing-new-and-simplified-ai-accelerator-driver-experience-rhel

    Since I already have the NVIDIA drivers installed on my two GPU enabled nodes, I will just confirm they are both running the same driver version (for consistency) and will ensure the driver is loading properly with nvidia-smi. I will also install CUDA and the nvidia-container-toolkit.


    Host Validation

    In my lab I have 2x Dell R730s with Nvidia Tesla T4s installed (Turing-class GPUs). They are not the most modern GPUs but they are Data center class, can be purchased pretty cheaply used, and only draw ~70w of power and therefore do not require any additional power connections from a riser card or the system board.

    So on each host we will first start off by insuring we have the proper NVIDIA drivers installed.

    [root@columbia ~]# rhel-drivers list
    Available drivers:
    amdgpu:latest
    > nvidia:590.48.01

    Now we run “nvidia-smi” to confirm the driver is loaded and the GPU is recognized.

    nvidia-smi
    Tue Feb 24 10:49:29 2026
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 580.105.08 Driver Version: 580.105.08 CUDA Version: 13.0 |
    +-----------------------------------------+------------------------+----------------------+
    | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
    | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
    | | | MIG M. |
    |=========================================+========================+======================|
    | 0 Tesla T4 Off | 00000000:04:00.0 Off | 0 |
    | N/A 34C P8 13W / 70W | 0MiB / 15360MiB | 0% Default |
    | | | N/A |
    +-----------------------------------------+------------------------+----------------------+

    Moving on 2 our second host and verify the installed driver.

    [root@prometheus ~]$ rhel-drivers list
    Available drivers:
    amdgpu:latest
    *> nvidia:590.48.01

    And nvidia-smi output, we can see that there are two Telsa T4s in this machine. Nice!

    [root@prometheus ~]$ nvidia-smi
    Tue Feb 24 10:52:55 2026
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 590.48.01 Driver Version: 590.48.01 CUDA Version: 13.1 |
    +-----------------------------------------+------------------------+----------------------+
    | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
    | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
    | | | MIG M. |
    |=========================================+========================+======================|
    | 0 Tesla T4 Off | 00000000:04:00.0 Off | 0 |
    | N/A 30C P8 9W / 70W | 0MiB / 15360MiB | 0% Default |
    | | | N/A |
    +-----------------------------------------+------------------------+----------------------+
    | 1 Tesla T4 Off | 00000000:06:00.0 Off | 0 |
    | N/A 32C P8 9W / 70W | 0MiB / 15360MiB | 0% Default |
    | | | N/A |
    +-----------------------------------------+------------------------+----------------------+

    Lets also make sure that we have the same CUDA version installed across hosts.

    [root@prometheus ~]$ rpm -qa | grep cuda-toolkit
    cuda-toolkit-config-common-13.1.80-1.noarch
    cuda-toolkit-13-config-common-13.1.80-1.noarch
    cuda-toolkit-13-1-config-common-13.1.80-1.noarch
    cuda-toolkit-13-1-13.1.1-1.x86_64
    cuda-toolkit-13.1.1-1.x86_64

    We also need to update $PATH for nvcc if we have not done so already.

    cat << 'EOF' | sudo tee /etc/profile.d/cuda.sh
    export PATH=/usr/local/cuda/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
    EOF

    Then source the path.

    # source /etc/profile.d/cuda.sh

    And now run nvcc.

    nvcc --version
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2025 NVIDIA Corporation
    Built on Tue_Dec_16_07:23:41_PM_PST_2025
    Cuda compilation tools, release 13.1, V13.1.115
    Build cuda_13.1.r13.1/compiler.37061995_0

    We also will need to install the Nvidia Container Toolkit on both GPU hosts, using the RHEL 9 version below.

    sudo dnf config-manager \
    --add-repo=https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo

    Once again we are going to skip the gpgcheck. Again this is a homelab.

    sudo dnf install -y --nogpgcheck nvidia-container-toolkit

    And now we validate install on both hosts.

    # nvidia-ctk --version
    NVIDIA Container Toolkit CLI version 1.18.2
    commit: 9e88ed39710fd94c7e49fbb26d96492c45e574fb

    Now we need to generate the CDI specification, as Podman does not use Docker-style run-times, and instead using Container Device Interface (CDI).

    sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

    The command above creates /etc/cdi/nvidia.yaml which describes installed GPUs and NVML libraries.
    We now need to restart podman and confirm podman sees our CDI devices.

    cat <<'EOF' | sudo tee /etc/containers/containers.conf.d/99-cdi.conf
    [engine]
    cdi_enabled=true
    cdi_spec_dirs=["/etc/cdi","/var/run/cdi"]
    EOF

    Now we need to verify podman can utilize our GPUs. Again we are running these commands on both our GPU enabled servers.

        podman run --rm --device nvidia.com/gpu=all docker.io/nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi -L
    GPU 0: Tesla T4 (UUID: GPU-9491a3e6-ea29-ba4e-4403-083244d5575c)
    GPU 1: Tesla T4 (UUID: GPU-1d877ac8-5df1-34b0-4f86-59945e37d2ba)
    
    

    DCGM install on RHEL 10

    The install is pretty straight forward, for this post I am performing these steps on both my GPU enabled hosts.

    Add Nvidia Repo

    Note that I could not find DCGM in the RHEL10 repos, so going with RHEL9 repos. Seems to work without issue thus far.

    # dnf config-manager --add-repo \
    https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo

    Now install as shown below.

    Note we are skipping the gpgcheck due to RHEL10 newer OpenGPG verification stack. Since this is a lab, and not production, this is acceptable for testing.

    # dnf install -y --nogpgcheck datacenter-gpu-manager-4-core datacenter-gpu-manager-4-proprietary

    Now we can start the service.

    # systemctl enable --now nvidia-dcgm

    And we check that the service is running.

    systemctl status nvidia-dcgm
    ● nvidia-dcgm.service - NVIDIA DCGM service
    Loaded: loaded (/usr/lib/systemd/system/nvidia-dcgm.service; enabled; preset: disabled)
    Active: active (running) since Tue 2026-02-24 10:37:35 EST; 36min ago
    Invocation: da9cd3a2c8a5463a95a3605b68adf253
    Main PID: 2263 (nv-hostengine)
    Tasks: 17 (limit: 1646190)
    Memory: 91.7M (peak: 93.1M)
    CPU: 23.253s
    CGroup: /system.slice/nvidia-dcgm.service
    └─2263 /usr/bin/nv-hostengine -n --service-account nvidia-dcgm
    Feb 24 10:37:35 prometheus.lab systemd[1]: Started nvidia-dcgm.service - NVIDIA DCGM service.
    Feb 24 10:37:37 prometheus.lab nv-hostengine[2263]: DCGM initialized
    Feb 24 10:37:37 prometheus.lab nv-hostengine[2263]: Started host engine version 4.5.2 using port number:>

    dcgmi discovery -l

    Now that dcgmi is installed lets confirm it can see our GPUs.

    This command lists all discovered GPUs. Shows GPU id, PCI BUS ID and Model Name. Should be comparable to the output of nvidia-smi. This command confirms that dcgmi can talk to the host engine.

    dcgmi discovery -l
    2 GPUs found (Active).
    +--------+----------------------------------------------------------------------+
    | GPU ID | Device Information |
    +--------+----------------------------------------------------------------------+
    | 0 | Name: Tesla T4 |
    | | PCI Bus ID: 00000000:04:00.0 |
    | | Device UUID: GPU-9491a3e6-ea29-ba4e-4403-083244d5575c |
    +--------+----------------------------------------------------------------------+
    | 1 | Name: Tesla T4 |
    | | PCI Bus ID: 00000000:06:00.0 |
    | | Device UUID: GPU-1d877ac8-5df1-34b0-4f86-59945e37d2ba |
    +--------+----------------------------------------------------------------------+

    Enable Health Watches

    Health Watches are background checks that DCGM performs on the GPU subsystems. While they are not required for metrics export they do provide additional metrics related to GPU health, so lets enable them.

    dcgmi health -s a
    Health monitor systems set successfully.

    dcgm-exporter

    NVIDIA DCGM Exporter is an open-source tool (container) that collects real-time telemetry data from NVIDIA GPUs—such as utilization, memory usage, temperature, and power consumption—and exposes them in a Prometheus-compatible format.

    We are going to run it via Quadlet ( /etc/containers/systemd/dcgm-exporter.container)

    [Unit]
    Description=NVIDIA DCGM Exporter
    After=network-online.target nvidia-dcgm.service
    Wants=network-online.target
    [Container]
    Image=docker.io/nvidia/dcgm-exporter:latest
    Network=host
    SecurityLabelDisable=true
    AddCapability=SYS_ADMIN
    PodmanArgs=–device nvidia.com/gpu=all
    PodmanArgs=–pid=host
    [Service]
    Restart=always
    [Install]
    WantedBy=multi-user.target
    view raw gistfile1.txt hosted with ❤ by GitHub

    Now lets start the container

     sudo systemctl daemon-reload
    [root@columbia ~]# sudo systemctl start dcgm-exporter.service
    [root@columbia ~]# podman ps
    CONTAINER ID  IMAGE                                  COMMAND     CREATED         STATUS         PORTS       NAMES
    8804d788f7f5  docker.io/nvidia/dcgm-exporter:latest              10 seconds ago  Up 10 seconds              systemd-dcgm-exporter
    
    

    Lets verify it is listening on port 9400.

    ss -tnlp | grep 9400
    LISTEN 0 4096 *:9400 *:* users:(("dcgm-exporter",pid=135704,fd=24))

    Now lets poke a hole in our firewall to allow the traffic.

    firewall-cmd --add-port=9400/tcp --permanent
    success
    [root@prometheus ~]$ sudo firewall-cmd --reload

    And test locally with curl.

    curl -s -o /dev/null -w "%{http_code}" http://10.1.10.23:9400/metrics

    We can also view the metrics in our browser

    Screenshot of a command-line output displaying NVIDIA GPU statistics including clock frequency, temperature, power usage, and memory utilization.

    Next steps will be to scrape and import.
    Which I will do after lunch.

    Resources

    Learn more from NVIDIA’s official resources:

  • Step-by-Step Nvidia Driver, CUDA Toolkit, & Container Toolkit Install for RHEL9

    Step-by-Step Nvidia Driver, CUDA Toolkit, & Container Toolkit Install for RHEL9

    Introduction

    In this step-by-steps guide we will replace the out of the box nouveau drivers on RHEL9 with Nvidia Drivers. We will also install the the Nvidia CUDA Toolkit and the Nvidia Container Toolkit.


    GPU and Driver Inspection

    First we need to make sure that our Nvdia GPU is recognized by Red Hat Enterprise Linux 9 (RHEL9).

    lspci -nn | grep -i nvidia
    b6:00.0 3D controller [0302]: NVIDIA Corporation GA102GL [A40] [10de:2235] (rev a1)
    

    Using the command below we can see that we are currently using the non-propietary nouveau driver.

    # lspci | grep ' NVIDIA ' | cut -d" " -f 1 | xargs -i lspci -v -s {}
    b6:00.0 3D controller: NVIDIA Corporation GA102GL [A40] (rev a1)
    	Subsystem: NVIDIA Corporation Device 145a
    	Flags: bus master, fast devsel, latency 0, IRQ 32, NUMA node 0
    	Memory at fa000000 (32-bit, non-prefetchable) [size=16M]
    	Memory at 38d000000000 (64-bit, prefetchable) [size=64G]
    	Memory at 38f040000000 (64-bit, prefetchable) [size=32M]
    	Capabilities: [60] Power Management version 3
    	Capabilities: [68] Null
    	Capabilities: [78] Express Legacy Endpoint, MSI 00
    	Capabilities: [b4] Vendor Specific Information: Len=14 <?>
    	Capabilities: [c8] MSI-X: Enable- Count=6 Masked-
    	Capabilities: [100] Virtual Channel
    	Capabilities: [258] L1 PM Substates
    	Capabilities: [128] Power Budgeting <?>
    	Capabilities: [420] Advanced Error Reporting
    	Capabilities: [600] Vendor Specific Information: ID=0001 Rev=1 Len=024 <?>
    	Capabilities: [900] Secondary PCI Express
    	Capabilities: [bb0] Physical Resizable BAR
    	Capabilities: [bcc] Single Root I/O Virtualization (SR-IOV)
    	Capabilities: [c14] Alternative Routing-ID Interpretation (ARI)
    	Capabilities: [c1c] Physical Layer 16.0 GT/s <?>
    	Capabilities: [d00] Lane Margining at the Receiver <?>
    	Capabilities: [e00] Data Link Feature <?>
    	Kernel driver in use: nouveau
    	Kernel modules: nouveau
    

    Configuring Repositories for the Nvidia Driver Install

    First we need to enable the RHEL9 CodeReady Builder repo. Note we are running these commands as root.

    # subscription-manager repos --enable codeready-builder-for-rhel-9-$(uname -i)-rpms
    

    Next we will need to install and configure the EPEL repo.

    # dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
    

    Now we install the ELRepo project repo – this will provide nvidia-detect which we can utilize later

    # dnf -y  install https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm

    Prerequisites for Nvidia Driver Install

    Now we need to install dependencies and build tools.

    # dnf install -y kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc make dkms acpid libglvnd-glx libglvnd-opengl libglvnd-devel pkgconfig
    

    Install Nvidia Drivers

    Install nvidia-detect from the ELRepo project repo.

    # dnf -y install nvidia-detect

    Now install the Nvidia Drivers.

    # dnf -y install $(nvidia-detect)

    Now reboot.


    Confirming Nvidia Driver Installation

    Now lets run the command below one more time.

    [root@gpu ~]# lspci | grep ' NVIDIA ' | cut -d" " -f 1 | xargs -i lspci -v -s {}
    b6:00.0 3D controller: NVIDIA Corporation GA102GL [A40] (rev a1)
    	Subsystem: NVIDIA Corporation Device 145a
    	Flags: bus master, fast devsel, latency 0, IRQ 32, NUMA node 0
    	Memory at fa000000 (32-bit, non-prefetchable) [size=16M]
    	Memory at 38d000000000 (64-bit, prefetchable) [size=64G]
    	Memory at 38f040000000 (64-bit, prefetchable) [size=32M]
    	Capabilities: [60] Power Management version 3
    	Capabilities: [68] Null
    	Capabilities: [78] Express Legacy Endpoint, MSI 00
    	Capabilities: [b4] Vendor Specific Information: Len=14 <?>
    	Capabilities: [c8] MSI-X: Enable- Count=6 Masked-
    	Capabilities: [100] Virtual Channel
    	Capabilities: [250] Latency Tolerance Reporting
    	Capabilities: [258] L1 PM Substates
    	Capabilities: [128] Power Budgeting <?>
    	Capabilities: [420] Advanced Error Reporting
    	Capabilities: [600] Vendor Specific Information: ID=0001 Rev=1 Len=024 <?>
    	Capabilities: [900] Secondary PCI Express
    	Capabilities: [bb0] Physical Resizable BAR
    	Capabilities: [bcc] Single Root I/O Virtualization (SR-IOV)
    	Capabilities: [c14] Alternative Routing-ID Interpretation (ARI)
    	Capabilities: [c1c] Physical Layer 16.0 GT/s <?>
    	Capabilities: [d00] Lane Margining at the Receiver <?>
    	Capabilities: [e00] Data Link Feature <?>
    	Kernel driver in use: nvidia
    	Kernel modules: nouveau, nvidia_drm, nvidia
    

    As you can see in the output below, the kernel is loading the Nvidia driver. We can still see nouveau kernel modules listed, but that is fine, as they are not loaded. We can confirm this with the command below.

    # lsmod | grep nouveau

    The above command should not output anything, while the opposite should be true for the command below.

    # lsmod | grep nvidia

    Configure Nvidia Persistenced

    Start and enable nvidia-persistenced.service. This will enable persistence-mode which will keep the nvidia device state from going “stale”

    # systemctl enable nvidia-persistenced.service
    # systemctl start nvidia-persistenced.service
    

    Installing the Nvidia CUDA Toolkit

    We will now follow the official guide and install the Nvidia CUDA toolkit. Per that guide, we need to enable a few repos, however two of those repos should be enabled by default, and the other one we enabled above, however I will list them here for the sake of documentation.

    # subscription-manager repos --enable=rhel-9-for-x86_64-appstream-rpms
    # subscription-manager repos --enable=rhel-9-for-x86_64-baseos-rpms
    # subscription-manager repos --enable=codeready-builder-for-rhel-9-x86_64-rpms

    Now we install the Nvidia repo for the CUDA toolkit.

    dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo
    

    Now install the CUDA toolkit as shown below

    # sudo dnf -y install cuda-toolkit

    Confirm that the toolkit is installed and note the version.

    # rpm -qa cuda-toolkit
    cuda-toolkit-12.8.1-1.x86_64
    

    Add the following to your .bashrc. And if you intend to run/install anything as root, you may want to add it to root’s .bashrc as well. Note that the cuda version should match the one that you installed above.

    export PATH=/usr/local/cuda-12.8/bin:$PATH

    Now test nvcc as shown below.

    # nvcc --version
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2025 NVIDIA Corporation
    Built on Fri_Feb_21_20:23:50_PST_2025
    Cuda compilation tools, release 12.8, V12.8.93
    Build cuda_12.8.r12.8/compiler.35583870_0
    

    Installing the Nvidia Container Toolkit

    Next we will install the Nvidia Container Toolkit, which allows users to run GPU-accelerated containerized applications.

    A bit about Container Management in RHEL 9

    The default container packages in RHEL 9 are as follows.

    1. Podman – daemonless container image
    2. Buildah – tool for building OCI (Open Container Initiative) container images
    3. Skopeo – tool for managing container images and repos
    4. CRIU – tool to create and save running container checkpoints to disk
    5. Udica – tool for managing SELinux policies for containers

    Installation of the toolkit

    We will follow the instructions as documented here.

    First we configure the repo

    # curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
      sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo

    Then install via dnf

    # dnf install -y nvidia-container-toolkit

    Configuring the Container Toolkit for Podman

    Generate the CDI specification file using the command below.

    # nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

    Now lets check the names of the generated device(s).

    # nvidia-ctk cdi list
    INFO[0000] Found 3 CDI devices                          
    nvidia.com/gpu=0
    nvidia.com/gpu=GPU-7e880be2-891c-72e3-9515-0fd51240e7f4
    nvidia.com/gpu=all
    

    References

    1. https://medium.com/@blackhorseya/step-by-step-guide-to-installing-nvidia-drivers-on-rhel-9-1107e0cd641d
    2. https://access.redhat.com/discussions/227d2101-b4e3-490a-aa1c-601c407ec038
    3. https://darryldias.me/2022/install-nvidia-drivers-on-rhel-9/
    4. https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
    5. https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#network-repo-installation-for-rhel-rocky
    6. https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/cdi-support.html
  • Resetting a Lost BMC Password with ipmitool

    Resetting a Lost BMC Password with ipmitool

    I recently got my hands on a couple of gigabyte servers. These machines came preinstalled with Ubuntu 20.04. Credentials for a OS local user account were on a sticker on the machines. However there was no indication of what the BMC credentials were. According to this document, there should be default credentials that we can use on the motherboard, however, they were not working.

    These machines came with Ubuntu 20.04 on them, and did not have ipmitool installed.

    $ sudo apt install ipmitool --fix-missing

    Once installed we need to determine what BMC users exist.

    $ sudo ipmitool user list 1

    In the output below you can see that there is one user – “admin” – identified as ID #2

    Now lets reset the password for “admin”.

    $ sudo ipmitool user set password 2

    We are then prompted to create a new password.

    We should now be able to load the BMC web interface and login with our new credentials