linuxcudagpunvidianvapi

How to get the number of connected displays to a gpu on Linux?


I need to determine whether a given CUDA device has displays connected or not. I know no CUDA function which does this.

On Windows, I can use NVAPI to get the number of connected displays and the PCI bus/slot id of each device. Using the latter, I can find the matching CUDA device (by calling cudaGetDeviceProperties).

How can I do the same on Linux, where NVAPI is not available?

Technically, what I need is a Linux alternative to the following code:

NvAPI_Initialize();

NvPhysicalGpuHandle gpuHandles[64];
NvU32 numOfGPUs;
NvAPI_EnumPhysicalGPUs(gpuHandles, &numOfGPUs);

for (int i = 0; i < numOfGPUs; i++)
{
    NvU32 connected_displays = 0;
    NvU32 busId = 0;
    NvU32 busSlotId = 0;

    NvAPI_GPU_GetConnectedDisplayIds(gpuHandles[i], NULL, &connected_displays, NULL);
    NvAPI_GPU_GetBusId(gpuHandles[i], &busId);
    NvAPI_GPU_GetBusSlotId(gpuHandles[i], &busSlotId);

    printf("Current device: %d\n", i);
    printf("Number of connected displays: %u\n", connected_displays);
    printf("Bus id: %u\tBus slot id: %u\n", busId, busSlotId);
}

NvAPI_Unload();

Solution

  • The most analogous approach under Linux would be to use the NVCtrl API which is what nvidia-settings, the linux NVIDIA control panel application, provides.

    How to download the nvidia-settings source package is documented in the linux driver release notes. Specifically, you can find various packages for specific driver versions here

    Choose a package that is closest to your driver version.

    Once you have downloaded and unzipped the nvidia-settings source, you will find a samples directory. In that directory is a sample program which has the necessary framework for what you want. Specifically, look in nv-control-targets.c. The following function in that file will do what you want:

        /* Connected Display Devices on GPU */
    
        ret = XNVCTRLQueryTargetAttribute(dpy,
                                          NV_CTRL_TARGET_TYPE_GPU,
                                          gpu, // target_id
                                          0, // display_mask
                                          NV_CTRL_CONNECTED_DISPLAYS,
                                          &display_devices);
        if (!ret) {
            fprintf(stderr, "Failed to query connected displays\n");
            return 1;
        }
        printf("   Display Device Mask (Connected) : 0x%08x\n",
               display_devices);
    

    Note that there are some preparatory/setup function calls at the top of that program (nv-control-targets.c) that will need to be executed as well.

    There is also a function (Display Mode) in NVML (nvidia-smi is based on NVML) that will inform you of whether the GPU is hosting a display or not, but I'm not sure it gives you the granularity you want.

    Actually, upon re-reading your question, NVML Display Mode might be sufficient for what you want. Referring to the API documentation here, p46:

    7.10.2.10 nvmlReturn_t DECLDIR nvmlDeviceGetDisplayMode (nvmlDevice_t device, nvmlEnableState_t 
    display)
    Retrieves the display mode for the device.
    For Tesla ™and Quadro ®products from the Fermi and Kepler families.
    This method indicates whether a physical display is currently connected to the device.
    See nvmlEnableState_t for details on allowed modes.
    Parameters:
    device The identifier of the target device
    display Reference in which to return the display mode
    Returns:
    • NVML_SUCCESS if display has been set
    • NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
    • NVML_ERROR_INVALID_ARGUMENT if device is invalid or display is NULL
    • NVML_ERROR_NOT_SUPPORTED if the device does not support this feature