• The Homelab Dilemma: Living With Enterprise Servers

    The Homelab Dilemma: Living With Enterprise Servers

    Enterprise Servers are loud and hot, and while a couple of 13th generation Dell servers kept a room nice and toasty in the cold of winter, it a double whammy to your electric bill in the Spring/Summer.

    The noise can be problematic as well, especially since I no longer have a basement, where I relied on my servers to circulate and dehumidify the stuffy air. Now, I actually have to sit in a room with the rack. Which is why I moved it to the bedroom. Strange.

    So why the bedroom, well the white noise (when under control) helps me sleep and I can turn down the heat in the Winter and not freeze at night. And in the day, when I power everything up, I am in my home office (or my second home office – the dinning room), which is already loud enough with my workstations and old Cisco switches. That tiny home office, that is technically a small bedroom for your least favorite child, can get downright uncomfortably warm.


    Why So Much Noise

    As anyone who has worked in a datacenter can tell you. Servers are loud. Let compare fans in an Dell R630 to an R730.

    ServerForm FactorEffective fan sizeFan CountNotes
    Dell R6301U~40 mm blower7 Very high RPM, loud, high static pressure
    Dell R7302U~60 mm blower6Still loud, but more efficient airflow

    This boils down to the 1U server must spin its fans faster that then 2U to move the same amount of air through the server chassis, measured in CFMs (Cubic Feet per Minute).

    Additionally, you install a PCIe card in a server that the server itself does not recognize (like Telsa T4 GPUs) , and you may find your fans spinning at full bore, as the server would rather take flight than overheat.


    Enter the Dell Fan Susher

    Luckily, you can use ipmitools to override a Dell server’s fan speed, and quiet things down a great deal. However, you need to keep your eye on temperatures. For this I created Dell-Server-Fan-Shusher.

    Its a python script that monitors system temps (via sensors), and NVIDIA GPU temps (via nvidia-smi – when present), and sets fan speeds accordingly. It currently has seven threshold levels for temp and fan speeds, all of which can easily be modified.

    Installation is one command and its scheduled either via cron or systemd.

    sudo ./install.sh

    The deployed fan_control.py reads system temps in the following order.

    • Sysfs (/sys/class/hwmon)
    • sensors
    • ipmitool sdr list (last fallback)

    It also gets GPU temps via nvidia-smi and system temps via IPMI (e.g. Inlet, Exhaust, CPU packages, etc.).


    Its Getting Hot in Here

    The susher has been working fine for months, but as I mentioned its no longer Winter and the ambient air in my “server room” has been rising. See output from my Netbotz 450 below. Starting to get hotter than a grandparent’s Florida condo.

    Line graph showing temperature readings over time from a sensor pod. The y-axis represents temperature in Fahrenheit, ranging from 71 to 77 degrees. The x-axis shows time intervals. The maximum temperature recorded is 75.4 degrees, and the minimum is 72.3 degrees.

    So why I am posting all this? So this morning, when I attempted to log into my main hypervisor to start on my 3rd installment of my HPC GPU Cluster journey, I found the host unresponsive and throwing the errors below on the console. Time to reboot.

    Terminal screen showing error messages for a network adapter in Red Hat Enterprise Linux, indicating it has stopped due to overheating and suggesting to restart the computer or replace the adapter.

    Overheating NIC?

    So here is what happened, the ixgbe driver detected that the adapter overheated and disabled it to protect the hardware. When that happens, all ports on that card stop working. In the console, kernel logs are reporting a thermal shutdown of the Intel 10GbE network adapter. Specifically the Intel X540-AT2, which is a dual port 10Gbe copper (RJ45) adapter – with a large heatsink (some variants of this card have a fan.

    lspci -s 0000:82:00.0
    82:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)

    A few minutes after a reboot the error returns, and the NIC goes offline again and is accessible only via the IDRAC console. At this point I cannot keep the system online long enough to do any meaningful troubleshooting. So we need to shush the susher. So from the console we disable it and then reboot again.

    # systemctl disable --now dell-r730-fan-control.timer
    Removed '/etc/systemd/system/timers.target.wants/dell-r730-fan-control.timer'.


    From our workstation we connect to the servers IDRAC and set manual fan control and set fan speeds to 100%. We do this while the target system is in the process or rebooting.

    ipmitool -I lanplus -H 10.1.10.20 -U root -P calvin raw 0x30 0x30 0x01 0x00
    ipmitool -I lanplus -H 10.1.10.20 -U root -P calvin raw 0x30 0x30 0x02 0xff 100

    Hopefully now we can keep the system online long enough to see what is really going on, as the server itself is not reporting any temperature issues on the idrac.


    Troubleshooting

    So first lets check the system logs and see how many times that this has occurred.

    grep -r "over heat\|overheat\|stopped because" /var/log/ 2>/dev/null | tail -50

    We see two events today, and a 3rd event a few days ago (probably patient zero).

    DateTimeEvent
    Mar 22, 202612:04:56Both Intel 10GbE NICs (enp130s0f0, enp130s0f1) stopped due to overheat
    Mar 22, 202613:17:24Same overheat again shortly before reboot at 13:24:59
    Mar 15, 202611:39:31Same overheat on both NICs

    Digging into logs a bit further, we see the following at around 12:04

    Fan speed: 15% (~3800 RPM)

    • GPU temp: 35°C
    • System temps: max 47°C (sensors 24–25 and 39 at 41–47°C)
    • Action: Fan control had just set fans to 15% for the “LOW” threshold.

    Intel X540-AT2 thermal specs

    A quick internet search yields the following. This NIC needs to get pretty hot to experience a thermal shutdown

    SpecificationValueNotes
    Operating temp (ambient)0°C to 55°CMarketing spec for 200 LFM airflow
    Extended ambient0°C to 70°CWith 300 LFM airflow and adequate heatsink
    Tcase max107°CMax case temp at heat spreader (die-level limit)

    NIC temperature visibility

    So the Intel ixgbe driver does not expose temperature to Linux:

    • No hwmon temperature sensor under /sys/...
    • ethtool does not show NIC temperature

    So there is no NIC temperature in system logs. The “over heated” message comes from the NIC’s internal thermal protection. The driver only reports the event; the actual NIC temperature is not logged. At this point we do no have a method to pull the temp from the NIC.

    Additional, there are no log messages like thermal warnings, throttling, or high-temperature notices before the shutdown. So there is really nothing that we can check for in the logs and use as a trigger for our Dell Fan Controller (Shusher).

    EventLast ixgbe message before overheatOverheat
    Mar 22, 12:04:5611:58:02 – NIC Link is Up 10 Gbps12:04:56 – overheat (about 7 minutes later)
    Mar 22, 13:17:2413:11:28 – NIC Link is Up 10 Gbps (after reboot)13:17:24 – overheat (about 6 minutes later)
    Mar 15, 11:39:31No ixgbe messages in preserved logs before this time11:39:31 – overheat

    Additionally, none of our reported temps from lm-sensors show any temperature issues, and we can see that the fan-susher had recently adjusted fans to 15% due to somewhat amenable temps.


    LM-Sensors

    Currently sensors detects the following temperatures on this R730.

    ChipSensorCurrentLimits
    coretemp-isa-0000 (CPU Package 0)Package id 028°Chigh 83°C, crit 93°C
    Core 0–28 (16 cores)22–25°Chigh 83°C, crit 93°C
    coretemp-isa-0001 (CPU Package 1)Package id 129°Chigh 83°C, crit 93°C
    Core 0–28 (16 cores)22–25°Chigh 83°C, crit 93°C

    Lets run sensors-detect and see if we can add any additional sensors that might help us get a better picture of temps across the system

    # sensors-detect

    We answer “Yes” at each prompt. Any new modules/sensors are added to /etc/sysconfig/lm_sensors

    Now we reload all the sensors

     . /etc/sysconfig/lm_sensors; for m in $HWMON_MODULES $BUS_MODULES; do [ -n "$m" ] && sudo modprobe -r $m 2>/dev/null; done; for m in $BUS_MODULES $HWMON_MODULES; do [ -n "$m" ] && sudo modprobe $m; done
    
    

    However, no new modules/temps are output by the sensors command, so no additional system temps to feed to the shusher.


    So What Now?

    At this point we have a few options, besides just cranking down the AC.

    We know that our overheat events occurred when system temps were ~47°C with fans at 15%. So, lets start with an overhaul of the susher and increase fan speeds by 10% for each of the 7 temp thresholds as configured in our .env file, and redeploy.

    Updated Fan speed levels (7 tiers)

    LevelTemp thresholdFan speedTrigger
    Very-Low< 20°C20%Below LOW
    Low≥ 20°C25%GPU LOW / System LOW
    Medium-Low≥ 35°C35%MED_LOW
    Medium≥ 50°C45%MED
    Medium-High≥ 60°C60%MED_HIGH
    High≥ 60°C (system) / 70°C (GPU)75%HIGH
    Very-High≥ 75°C90%Auto mode → iDRAC

    Our minimum fan speed is now 20% instead of 10%, which should improve airflow over the NICs and reduce overheat risk.

    Inlet/Exhaust Differential Logging

    For the NIC overheat events (Mar 22 12:04, 13:17 and Mar 15 11:39), inlet/exhaust were not logged, so let’s start logging them on each scheduled run of fan_control.py , so if/when something goes wrong, we can see how hot the air was going in and how much it warmed up inside the chassis.

    Safety Floor

    Additionally lets setup login in fan_control.py if inlet or exhaust gets too high:

    • Inlet ≥ 40°C → minimum fan speed set to 35%
    • Exhaust ≥ 50°C → minimum fan speed set to 35%

    Even if GPU/CPU temps look fine, we still ramp fans to protect things like the NIC when chassis air is hot.


    Next Steps

    For now we are going to let things ride. We have adjusted our fan speeds up, and we setup our safety floor.

    If we continue to see issues, we may need to take additional action. This r730 is running a number of Virtual machines which I use as “lab infrastructure”, so I want it running 24/7. And while I could just keep jacking up fan speeds, I would rather take a more proactive approach.

    1. Remove heatsink and apply fresh thermal paste. This card is long in the tooth. Could be dried up.
    2. Move to an earlier revision of the Intel X540-AT2 which came with active fans. (Cheap)
    3. Move to a card who’s driver can expose temperatures, like the Broadcom NetXtreme-E (e.g. BCM57416 – not as cheap)

    In theory, I like the 3rd option, as it would be nice to be able to pull temperatures from the the NIC, and allow fan_control.py to actually adjust fan speeds intelligently. In practice, however, replacing the NIC is probably overkill unless I run into a dual port actively cooled Intel with both long and short brackets (I like to keep my options open slot-wise). Although I do like getting packages in the mail.

  • 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
  • CPU Overclocking on Ubuntu 24.04

    CPU Overclocking on Ubuntu 24.04

    One of my workstations has a Intel Core i7-8086K Special Edition CPU. Its a 40th-anniversary limited edition 6-core/12-thread Coffee-Lake processor launched in 2018 to commemorate the original Intel 8086 processor. The i7-8086K features a base clock speed of 4.0GHz and a boost speed of 5.0GHz.

    As this processor was not a standard mass-produced model, its a bit collectible in some strange circles. It was also the first Intel processor to hit 5.0GHz out of the box. Technically the i7-8086K is a “cherry-picked” or higher-binned version of the popular Intel Core i7-8700K. Because these chips were selected from the best-performing parts of the wafer, they typically require less voltage to run at high speeds. At the time enthusiasts were willing to pay a premium as these chips are much more likely to reach stable overclocks of 5.1 GHz to 5.3 GHz across all cores.

    Nowadays the Intel Core i7-8086K Special Edition CPU still maintains a “legacy premium” price, even on eBay where they are still over $100 per.

    So lets overclock it a bit.


    Installing CPU Frequency Tools in Ubuntu

    Lets start by installing the tools to allow us to modify the cpu governor and inspect CPU frequencies

    sudo apt install linux-tools-common linux-tools-$(uname -r) cpufrequtils

    Set CPU Governor to Performance

    The performance governor prevents Linux from aggressively downclocking the CPU.

    sudo cpupower frequency-set -g performance

    Set Overclock on Boot Via Systemd

    We want our overclock to be persistent across reboots, so we will create a systemd service that will run at boot-time.

    vim /etc/systemd/system/cpupower.service

    Copy/Paste the contents below in to the file we are creating above.

    [Unit]
    Description=CPU performance governor
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/cpupower frequency-set -g performance
    [Install]
    WantedBy=multi-user.target

    Now we need to enable and start the service.

    sudo systemctl enable --now cpupower

    Confirm Overclock

    First we will run a quick frequency check. Here the CPU(s) scaling MHz indicates the percentage of the CPU’s maximum possible frequency that the system is currently running at (on average across cores). Meaning that the CPU is currently operating at ~42% of its maximum clock frequency across all CPUs.

    lscpu | grep MHz
    CPU(s) scaling MHz: 42%
    CPU max MHz: 5100.0000
    CPU min MHz: 800.0000

    Via the cpupower command we can we that we currently have one boosted core running at 5.07Ghz.

    root@raptor:/etc/chrony# cpupower frequency-info
    analyzing CPU 7:
    driver: intel_pstate
    CPUs which run at the same hardware frequency: 7
    CPUs which need to have their frequency coordinated by software: 7
    energy performance preference: performance
    hardware limits: 800 MHz - 5.10 GHz
    available cpufreq governors: performance powersave
    current policy: frequency should be within 800 MHz and 5.10 GHz.
    The governor "performance" may decide which speed to use
    within this range.
    current CPU frequency: 5.07 GHz (asserted by call to kernel)
    boost state support:
    Supported: yes
    Active: yes

    We can run the watch command against /proc/cpu info and watch frequencies change real-time.

    Terminal output displaying CPU frequencies in MHz, showing varying values for multiple CPU cores.

    Generate Load to Drive Up Frequencies

    In a second ssh window we will now install and run stress-ng to generate some load, while we continue to run our watch command above.

    sudo apt install stress-ng

    Once installed we run it as shown below

    Where:

    • –cpu 0 = use all online CPUs
    • matrixprod is a decent compute-heavy load

    In our watch window we can see we have all cores above 4.0GHz

    Terminal output showing CPU frequency readings in MHz, displaying values around 4399 to 4400 MHz.

    Checking CPU Temps

    My Intel Core i7-8086K Special Edition CPU has a pretty average cpu cooler/fan. Nothing fancy with heat-pipes and multiple fans, however I do have 8x 120mm case fans moving a lot of air through my case, while projecting nice purple glow. So lets check our CPU temps, first at rest and then under load.

    So we start by installing lm-sensors, and then detect available sensors. Sensors-detect will ask you a handful of questions, but you can usually stick with the defaults.

    sudo apt install lm-sensors
    sudo sensors-detect

    And now we check temps at rest

    ~# sensors
    coretemp-isa-0000
    Adapter: ISA adapter
    Package id 0: +34.0°C (high = +82.0°C, crit = +100.0°C)
    Core 0: +33.0°C (high = +82.0°C, crit = +100.0°C)
    Core 1: +33.0°C (high = +82.0°C, crit = +100.0°C)
    Core 2: +34.0°C (high = +82.0°C, crit = +100.0°C)
    Core 3: +36.0°C (high = +82.0°C, crit = +100.0°C)
    Core 4: +33.0°C (high = +82.0°C, crit = +100.0°C)
    Core 5: +33.0°C (high = +82.0°C, crit = +100.0°C)

    So lets kick off stress-ng to generate some load, which we ‘watch’ the output of the sensors command in another terminal window.

    stress-ng --cpu 0 --cpu-method matrixprod --timeout 60s --metrics-brief

    And we can see that we get a bit toasty. While these temperatures are high, they are not dangerous to see during a stress test. What we do know is that we do not have a lot of thermal headroom.

    Screenshot of system temperature readings from a tool showing CPU core temperatures with values in Celsius, indicating critical and high temperature thresholds.

    Stress-ng is built to generate worst-case thermal load when running, so I really and not concerned to see these temps when its running.

    Just to be sure, lets run turbostat and see if we see any throttling.

    sudo turbostat --interval 1

    Turbostat produces a lot of output, the table below will give you an idea of what you are looking at.

    ColumnWhat it ShowsWhat You Want to See
    PkgTmpCPU package temperatureIdeally <90 °C during sustained load
    CoreTmpPer-core temperatureSimilar to package temp; watch for cores hitting 95 °C+
    Avg_MHzAverage CPU frequency during the intervalShould rise close to the overclock max under load
    Bzy_MHzActual frequency while the core is busyShould approach the configured turbo (≈5 GHz)
    Busy%CPU utilization per coreNear 100% during stress-ng
    PkgWattTotal CPU package powerUseful to understand thermal load
    CorWattPower used by coresIndicates how much compute load is occurring

    For thermal events or power throttling we look for the following.

    ColumnMeaning
    ThermThrotThermal throttling events
    Pkg%pc2 / pc3 / pc6Package idle states (should drop during stress)
    Core%pc3 / pc6Core idle states

    If cpu performance/speed was throttled we would expect to see ThermThrot events.

    If you want a cleaner, and more succinct output from turbostat, try the one-liner below.

    sudo turbostat --interval 1 --quiet --show CPU,Busy%,Bzy_MHz,Avg_MHz,PkgTmp,CoreTmp,ThermThrot

    While we are not seeing any throttling events, we do see that across all CPU cores we have a BZY_MHz of 4400 MHz (not 5000MHz). Since our test workload is running across all cores/threads (12 logical CPUs in this case), the processor switches the the all-core turbo limit of 4.4GHz which is lower than the single core turbo frequency of ~5.0GHz. This is good news and shows we are stable across all cores, but does not allow us to hit the max turbo frequency for this cpu.

    So lets try that.

    Lets run a load on exactly one core.

    stress-ng --cpu 1 --taskset 0 --timeout 60

    In another terminal window we run our watch command, where we can see that we are in fact able to hit almost 5.1Ghz.

    sudo turbostat --interval 1 --show CPU,Bzy_MHz,PkgTmp
    CPU Bzy_MHz PkgTmp
    - 5098 53
    0 5099 53

    Cool, over 5.0GHz.

    Not that I am looking to push it any further above 5.0GHz, but if I was, a better cpu cooler would be the way to go (and possibly some tweaking in the bios). That being said, at our current speeds as we never got hot enough to see any throttling. May look for a glowing purple one anyway.

  • 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:

  • Fix GPG Check Failed Error on RHEL 10.1

    Overview

    On some RHEL 10.1 installs users are running into this error, post-install, when attempting to install packages via dnf.

    Unsure if the issue is isolated to users attempting to install RHEL via the full DVD ISO, from the minimal boot ISO, and users deploying RHEL 10.1 via kickstart.

     GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
    The GPG keys listed for the "Red Hat Enterprise Linux 10 for x86_64 - AppStream (RPMs)" repository are already installed but they are not correct for this package.
    Check that the correct key URLs are configured for this repository.. Failing package is: gnupg2-smime-2.4.5-3.el10_1.x86_64
     GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
    The downloaded packages were saved in cache until the next successful transaction.
    You can remove cached packages by executing 'yum clean packages'.
    Error: GPG check FAILED

    More Details

    The issue is caused by GPG keys installed in /etc/pki/rpm-gpg, specifically RPM-GPG-KEY-redhat-release

    This issue is being tracked via BUG RHEL-144980


    Workaround

    I am currently aware of two workaround, one manual, one much more simple. Details below


    Workaround #1 (Simple)

    Use dnf to install new GPG keys used via dnf

    $ sudo dnf update redhat-release

    After doing so you should run the following

    $ sudo dnf clean all

    You should now be able to update RHEL and install additional RPMs.


    Workaround #2 (manual)

    You can delete the current key in “/etc/pki/rpm-gpg”

    Delete the following

    • RPM-GPG-KEY-redhat-release
    • RPM-GPG-KEY-redhat-beta (if applicable)

    Then SCP known working copies of the keys that you just deleted from a RHEL 10.1 host that is not experiencing this issue. I would suspect an earlier build of RHEL 10.1 or possibly a later build or RHEL 10.1 once available will not experience this issue.

    Once you replace the keys, clean up dnf cache

    $ sudo dnf clean-all