2

我刚刚开始使用 CUDA,想知道如何最好地将主机端API 与 C++ 一起使用。我对任何 C API 的最初倾向是用内联函数和方法包装它,在错误返回时添加异常,以便它与我的其余代码很好地融合。我已经简要介绍了推力,但这似乎是一个更高级别的东西,并且不包含您可能需要使用的其他 API。

是否存在我缺少的现有包装器,或者是否有充分的理由直接使用我忽略的 C API?

更新:我确实找到了一个类似于我正在寻找的名为<Cuda> 模板的库。它比我想要的更抽象,所以我可能不会使用它,但我把它放在这里作为参考,以防其他人有同样的问题。

4

4 回答 4

4

CUDA 调用通常与内核调用密切相关。例如,您可能会分配一些内存,cudaMalloc()然后在该内存上运行内核。内核本身、调用内核的代码(使用三括号语法)和设置一些资源(如纹理)的代码都必须在 .cu 文件中。

正因为如此,我认为最好只创建小型 C 风格的库来包装与一个内核(或几个紧密相关的内核)相关的功能。然后,如果需要,可以将该 C 样式库封装在 C++ 接口中。

因此,例如,C 风格的库可能有一个init()调用来设置内核运行所需的所有资源compute()、调用一个或多个内核的deinit()调用以及释放所有内容的调用。然后,如果需要,您可以拥有一个 C++ 类,该类init()在其构造函数、deinit()析构函数中compute()调用,并使用检查返回值并可能引发异常的方法包装调用。

于 2012-06-13T17:07:45.443 回答
2

据我所知,不存在这样的事情。如果您只想在出错时抛出异常,请考虑使用thrust::system_error.

例如:

#include <thrust/system_error.h>

void my_cudaMalloc_wrapper(void **devPtr, size_t size)
{
  cudaError_t error = cudaMalloc(devPtr, size);
  if(error != cudaSuccess)
  {
    throw thrust::system_error(error, thrust::cuda_category());
  }
}

thrust::system_error源自std::runtime_error。它的.what()成员函数将为您解码 CUDA 运行时错误:

#include <iostream>

void foo()
{
  int *ptr = 0;
  size_t n = 13;
  try
  {
    my_cudaMalloc_wrapper(&ptr, n);
  }
  catch(std::runtime_error &error)
  {
    std::cerr << "Uh oh: " << error.what() << std::endl;
  }
}
于 2012-06-13T01:07:12.750 回答
1

你可以这样做。但是,在最低级别用 C++ 替换 C 习语并不总是可行的。例如,执行完整的 RAII 通常是低效的:在 GPU 上初始化数组可能比在 CPU 上慢得多,并且通常可以使用“未初始化”模式设计内核来替代这个昂贵的步骤。您可以直接在 C++ 类中管理此类内容,但 IMO 将其放在额外的 C 层中会更安全一些,因为没有人期望一切都很好地 RAIIed。

于 2012-06-12T21:49:23.570 回答
1

我的回答并不完整。根据我研究 CUDA 时的记忆,可以在这些内核中运行的代码类型非常有限。分配给每个内核的私有内存空间非常少,因此不能有大的堆栈、堆分配的对象以及 C++ 擅长的所有好东西,这使得 C++ 对于 CUDA 目的几乎毫无用处。因此,即使有包装器,由于限制,使用起来也不实用

于 2012-06-12T21:26:11.460 回答