我参与了将 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。
感谢您的见解和建议。