如何从 C# 调用 CUDA

Sha*_*e57 4 c# pinvoke cuda gpu

我使用 Hybridizer 构建了一个程序,用 C# 编写 CUDA 代码并调用函数。该程序可以正常运行,但我注意到设置 GPU 并调用其函数的开销非常高。例如,在 CPU 上运行时需要 3000 个时钟周期的作业需要大约 5000 万个时钟周期来设置 GPU 包装器,然后在 GPU 上运行时需要另外 5000 万个时钟周期。我试图弄清楚这种滞后是否是由于 Hybridizer 本身造成的,或者是从我的 C# 程序调用 GPU 代码时不可避免的。

所以我正在寻找替代方法。我的搜索发现一些提到了 P/invoke 的东西,但我真的找不到关于如何使用它的好指南,而且所有这些线程都有 9 年以上的历史了,所以我不知道它们的信息是否仍然相关。我还发现了一些有关 ManagedCuda 的内容,但似乎不再开发。

Den*_*kiy 6

您可以尝试使用CppSharp生成与 CUDA 的 C# 绑定。我们能够使用这种方法初始化 CUDA 并调用它的简单硬件信息函数(GetDeviceProperties、CudaSetDevice、CudaGetDeviceCount、CudaDriverGetVersion、CudaRuntimeGetVersion)。

使用 CUDA API 的其他部分似乎是可能的,但我们没有尝试:CppSharp 为整个 CUDA 运行时 API 生成了绑定。我们通过 NVIDIA 的 Flex 库间接使用 CUDA。所有 Flex 函数都可以通过 CppSharp 使用,而不会造成相当大的损失。

通过 CppSharp 生成的类的示例用法如下所示:

int driverVersion = 0;
CudaRuntimeApi.CudaDriverGetVersion(ref driverVersion);

int runtimeVersion = 0;
CudaRuntimeApi.CudaRuntimeGetVersion(ref runtimeVersion);

int deviceCount = 0;
var errorCode = CudaRuntimeApi.CudaGetDeviceCount(ref deviceCount);

if (errorCode != CudaError.CudaSuccess)
{
    Console.Error.WriteLine("'cudaGetDeviceCount' returned " + errorCode + ": " + CudaRuntimeApi.CudaGetErrorString(errorCode));
    return;
}

for (var device = 0; device < deviceCount; ++device)
{
    using (var deviceProperties = new CudaDeviceProp()) 
    {
        CudaRuntimeApi.CudaGetDeviceProperties(deviceProperties, device);
    }
}
         
Run Code Online (Sandbox Code Playgroud)

CudaRuntimeApi 和 CudaDeviceProp 是 CppSharp 生成的类。

  • 为什么不提供一个例子呢? (5认同)
  • C# 部分。您可以简单地演示如何从 C# 运行“deviceQuery”等示例代码。用作示例的 CUDA 代码并不那么重要,但很高兴看到一些完整且有效的代码。我在答案中提供了许多完整的示例,甚至包括 OpenMP 和从 python 调用 CUDA 代码之类的示例。没有人按在这里发布的单词或字符向您收费,因此在我看来,极端简洁并不是一个如此答案中真正有吸引力的功能。[此处](/sf/ask/3186086851/) 是使用 ctypes 从 python 调用 CUDA 的示例。 (2认同)
  • @罗伯特·克罗维拉,哦,我明白了。我会尝试发布代码。 (2认同)