如何将统一内存应用于现有对齐的主机内存
How to apply Unified Memory to existing aligned host memory
我参与了将 CUDA 集成到一些现有软件中的工作。我要集成的软件是伪实时的,所以它有一个内存管理器库,可以手动传递来自预先分配的单个大内存分配的指针。 CUDA 的 Unified Memory 对我们很有吸引力,因为理论上我们可以将这个大内存块更改为 Unified Memory,现有的 CPU 代码仍然有效,并且允许我们添加 GPU 内核,只需很少的改动到现有数据 I/O 流。
我们现有的部分 CPU 处理代码要求内存与特定对齐方式对齐。 cudaMallocManaged() 不允许我指定内存的对齐方式,我觉得必须在这些 CPU 部分的 "managed" 和严格的 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) 时,最后的 print 语句打印 0。通过内核启动的设备访问在较大的文件中毫不奇怪地报告非法访问。
当使用 cudaMallocManaged() (USE_HOST_REGISTER == 0) 时,最后的打印语句按预期打印 1。
编辑:cudaHostRegister() 和 cudaMallocManaged() 为我做 return 成功错误代码。在我共享的示例中留下了这个错误检查,但我在初始集成工作期间确实检查了它们。刚刚添加了代码进行检查,两者仍然 return CUDA_SUCCESS.
感谢您的见解和建议。
CUDA 中目前没有可用的方法来获取现有主机内存分配并将其转换为托管内存分配。
我参与了将 CUDA 集成到一些现有软件中的工作。我要集成的软件是伪实时的,所以它有一个内存管理器库,可以手动传递来自预先分配的单个大内存分配的指针。 CUDA 的 Unified Memory 对我们很有吸引力,因为理论上我们可以将这个大内存块更改为 Unified Memory,现有的 CPU 代码仍然有效,并且允许我们添加 GPU 内核,只需很少的改动到现有数据 I/O 流。
我们现有的部分 CPU 处理代码要求内存与特定对齐方式对齐。 cudaMallocManaged() 不允许我指定内存的对齐方式,我觉得必须在这些 CPU 部分的 "managed" 和严格的 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) 时,最后的 print 语句打印 0。通过内核启动的设备访问在较大的文件中毫不奇怪地报告非法访问。
当使用 cudaMallocManaged() (USE_HOST_REGISTER == 0) 时,最后的打印语句按预期打印 1。
编辑:cudaHostRegister() 和 cudaMallocManaged() 为我做 return 成功错误代码。在我共享的示例中留下了这个错误检查,但我在初始集成工作期间确实检查了它们。刚刚添加了代码进行检查,两者仍然 return CUDA_SUCCESS.
感谢您的见解和建议。
CUDA 中目前没有可用的方法来获取现有主机内存分配并将其转换为托管内存分配。