我参与了将CUDA集成到某些现有软件中的工作。我要集成的软件是伪实时的,因此它具有内存管理器库,该库可以手动传递来自预先分配的单个大内存分配的指针。 CUDA的统一内存对我们很有吸引力,因为从理论上讲,我们可以将较大的内存块更改为统一内存,使现有的CPU代码仍然有效,并允许我们对现有数据进行很小的更改即可添加GPU内核。 I / O流。
我们现有的CPU处理代码的某些部分要求将内存对齐到某些对齐方式。 cudaMallocManaged()不允许我指定内存的对齐方式,并且我觉得必须在“托管”缓冲区和严格的CPU缓冲区之间进行复制,这些CPU部分几乎无法达到UM的目的。有没有一种已知的方法可以解决我所缺少的问题?
我在Stack Overflow上发现this link似乎在理论上解决了该问题,但是我无法用这种方法产生良好的结果。使用CUDA 9.1,Tesla 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。
感谢您的见解和建议。
答案 0 :(得分:1)
CUDA中当前没有可用的方法来获取现有主机内存分配并将其转换为托管内存分配。