Pid*_*AWK 5 c memory memory-management cuda mmap
我正在尝试创建一个包含uint32_ts的映射内存文件,然后将其用作 CUDA 的零拷贝固定内存,如下所示。我在获取cudaErrorInvalidValue设备指针时得到了,分配了空间并从文件映射了内存。我知道错误消息(来自 API)意味着:
这表明传递给 API 调用的一个或多个参数不在可接受的值范围内。
但我正在努力弄清楚为什么我会遇到这个问题......有什么想法吗?提前致谢。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
…
int main(void)
{
struct stat buf;
…
uint32_t *data, *dev_data;
cudaDeviceProp cuda_prop;
cudaGetDeviceProperties(&cuda_prop, 0);
if (!cuda_prop.canMapHostMemory)
exit(EXIT_FAILURE);
cudaSetDeviceFlags(cudaDeviceMapHost);
int data_file = open(data_file_name, O_RDONLY);
int stat = fstat(sa_file, &buf);
int data_file_size = buf.st_size;
err = cudaHostAlloc((void**)&data, data_file_size, cudaHostAllocMapped);
if (err == cudaErrorMemoryAllocation) exit(EXIT_FAILURE);
data = (uint32_t*) mmap(0, data_file_size, PROT_READ, MAP_PRIVATE, data_file, 0);
err = cudaHostGetDevicePointer((void**)&dev_data, (void*)data, 0);
if (err == cudaErrorMemoryAllocation)
{
printf("cudaHostGetDevicePointer - Mem Alloc Err\n");
exit(EXIT_FAILURE);
}
else if (err == cudaErrorInvalidValue) //ERROR HERE.
{
printf("cudaHostGetDevicePointer - Invalid Val Err\n");
exit(EXIT_FAILURE);
}
…
}
Run Code Online (Sandbox Code Playgroud)
一个问题是你的程序的逻辑顺序不正确。data此行分配一个由 CUDA API 提供的值:
err = cudaHostAlloc((void**)&data, data_file_size, cudaHostAllocMapped);
Run Code Online (Sandbox Code Playgroud)
然后这一行用一个新值覆盖该值:
data = (uint32_t*) mmap(0, data_file_size, PROT_READ, MAP_PRIVATE, data_file, 0);
Run Code Online (Sandbox Code Playgroud)
此时,dataCUDA API 不再将 的值识别为固定内存空间,因此当您调用此方法时:
err = cudaHostGetDevicePointer((void**)&dev_data, (void*)data, 0);
Run Code Online (Sandbox Code Playgroud)
您会收到错误,因为data无法识别 中包含的值。
编辑:(基于这个问题)除了这个问题之外,似乎如果您将文件处理从只读更改为读写,那么这个过程就可以工作(不会抛出运行时错误)。这是演示这一点的完整代码(不包含上述逻辑缺陷)(我之前创建了一个test.dat大小为 566316 字节的文件):
$ cat t706.cu
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
int main(void)
{
struct stat buf;
char *dev_data;
cudaDeviceProp cuda_prop;
cudaGetDeviceProperties(&cuda_prop, 0);
if (!cuda_prop.canMapHostMemory)
exit(EXIT_FAILURE);
cudaSetDeviceFlags(cudaDeviceMapHost);
int data_file = open("test.dat", O_RDWR);
int stat = fstat(data_file, &buf);
int data_file_size = buf.st_size;
printf("data_file_size = %d\n", data_file_size);
char *data = (char *) mmap(0, data_file_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, data_file, 0);
if (data == MAP_FAILED) {
printf("mmap failure\n");
exit(EXIT_FAILURE);}
cudaError_t err = cudaHostRegister(data, data_file_size, cudaHostRegisterDefault);
if (err != cudaSuccess) { //ERROR HERE.
printf("cudaHostRegister fail\n");
exit(EXIT_FAILURE);}
err = cudaHostGetDevicePointer((void**)&dev_data, (void*)data, 0);
if (err == cudaErrorMemoryAllocation)
{
printf("cudaHostGetDevicePointer - Mem Alloc Err\n");
exit(EXIT_FAILURE);
}
else if (err == cudaErrorInvalidValue)
{
printf("cudaHostGetDevicePointer - Invalid Val Err\n");
exit(EXIT_FAILURE);
}
}
$ nvcc -arch=sm_30 -o t706 t706.cu
$ ./t706
data_file_size = 566316
$
Run Code Online (Sandbox Code Playgroud)