You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用NVML库nvmlDeviceGetAccountingPids时uint数组赋值异常

解决方案:正确调用NVML的nvmlDeviceGetAccountingPids获取GPU进程PID

问题根源

你的代码能正确返回进程数量,但PID数组全为0,核心问题有两点:

  • 未遵循NVML数组查询函数的标准流程:需要先调用函数获取实际所需的数组大小,再分配对应内存执行查询
  • 数组参数的封送属性配置不当,导致原生函数无法向C#数组写入数据

修正方案

1. 调整DllImport签名

明确pids参数的封送属性为[Out],告知CLR原生函数会向该数组写入数据:

[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlDeviceGetAccountingPids(IntPtr device, ref uint count, [Out] uint[] pids);

2. 遵循标准调用流程

NVML的这类数组查询函数需要分两步调用:

  • 第一步:传入count=0,获取实际存在的PID数量
  • 第二步:根据获取的数量分配数组,再次调用函数获取完整PID列表

3. 完善错误检查

每次NVML函数调用后都要校验返回值,比如NVML_ERROR_INSUFFICIENT_SIZE是数组大小不足的标准错误码,可作为流程分支依据

修改后的完整调用代码

替换你Main方法中的PID查询逻辑:

// 第一步:获取实际PID数量
uint count = 0;
nvmlReturn_t result = nvmlDeviceGetAccountingPids(_device, ref count, null);
if (result == nvmlReturn_t.NVML_ERROR_INSUFFICIENT_SIZE && count > 0)
{
    // 第二步:分配对应大小的数组
    uint[] pids = new uint[count];
    result = nvmlDeviceGetAccountingPids(_device, ref count, pids);
    if (result == nvmlReturn_t.NVML_SUCCESS)
    {
        Console.WriteLine($"GPU {i} ({name}) 的占用进程PID:");
        foreach (uint pid in pids)
        {
            if (pid != 0) // 过滤可能的空值
                Console.WriteLine(pid);
        }
    }
    else
    {
        Console.WriteLine($"获取PID失败:{result}");
    }
}
else if (result == nvmlReturn_t.NVML_SUCCESS && count == 0)
{
    Console.WriteLine($"GPU {i} ({name}) 无占用进程");
}
else
{
    Console.WriteLine($"查询PID数量失败:{result}");
}

额外注意事项

  • 确认GPU支持Accounting功能:可调用nvmlDeviceGetAccountingMode检查状态,若未开启,需调用nvmlDeviceSetAccountingMode开启(需管理员权限)
  • 所有NVML函数调用都应检查返回值,这能快速定位权限不足、驱动未加载等问题

内容的提问来源于stack exchange,提问作者codingNewb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:54:22