1

我参与了将 CUDA 集成到一些现有软件中的工作。我要集成的软件是伪实时的,所以它有一个内存管理器库,可以手动传递来自预先分配的单个大内存分配的指针。CUDA 的统一内存对我们很有吸引力,因为理论上我们可以将这个大内存块更改为统一内存,让现有的 CPU 代码仍然工作,并允许我们添加 GPU 内核,而对现有数据的更改很少I/O 流。

我们现有的 CPU 处理代码的一部分需要内存对齐到一定的对齐。cudaMallocManaged() 不允许我指定内存对齐方式,我觉得必须在这些 CPU 部分的“托管”和严格 CPU 缓冲区之间进行复制几乎违背了 UM 的目的。有没有已知的方法来解决我缺少的这个问题?

我在 Stack Overflow 上找到了这个链接,理论上似乎可以解决它,但我无法用这种方法产生好的结果。使用 CUDA 9.1、特斯拉 M40 (24GB):

#include <stdio.h>
#include <malloc.h>
#include <cuda.h>

#define USE_HOST_REGISTER 1

int main (int argc, char **argv)
{
   int num_float = 10;
   int num_bytes = num_float * sizeof(float);

   float *f_data = NULL;

   #if (USE_HOST_REGISTER > 0)
   printf(
      "%s: Using memalign + cudaHostRegister..\n",
       argv[0]);

   f_data = (float *) memalign(32, num_bytes);

   cudaHostRegister(
      (void *) f_data,
      num_bytes,
      cudaHostRegisterDefault);
   #else
   printf(
      "%s: Using cudaMallocManaged..\n",
       argv[0]);

   cudaMallocManaged(
      (void **) &f_data,
      num_bytes);
   #endif

   struct cudaPointerAttributes att;
   cudaPointerGetAttributes(
      &att,
      f_data);

   printf(
      "%s: ptr is managed: %i\n",
       argv[0],
       att.isManaged);
   fflush(stdout);

   return 0;
}

当使用 memalign() + cudaHostRegister() (USE_HOST_REGISTER == 1) 时,最后一个打印语句打印 0。通过内核在较大文件中启动的设备访问会报告非法访问。

使用 cudaMallocManaged() (USE_HOST_REGISTER == 0) 时,最后一个打印语句按预期打印 1。

编辑: cudaHostRegister() 和 cudaMallocManaged() 确实为我返回成功的错误代码。在我共享的示例中留下了这个错误检查,但我在最初的集成工作中确实检查了它们。刚刚添加了要检查的代码,两者仍然返回 CUDA_SUCCESS。

感谢您的见解和建议。

4

1 回答 1

2

目前在 CUDA 中没有可用的方法来获取现有的主机内存分配并将其转换为托管内存分配。

于 2019-05-08T20:28:18.910 回答