将映射的Linux字符设备内存注册到CudaHosterRegister会导致参数无效
我正试图通过以下方式促进DMACPUGPU数据传输: 1.将我的(专有)设备Linux内核分配的内存映射到用户空间 2.使用cudaHostRegister API函数将后一个(映射内存)注册到Cuda 虽然映射映射到我的设备DMA的用户空间分配内存,然后使用cudaHostRegister注册到Cuda工作正常,但尝试注册“KAlloced”内存会导致cudaHostRegister返回“Invalid Argument”错误 首先,我认为问题在于对齐或我的设备驱动程序复杂的内存池管理,因此我编写了一个最简单的字符设备,它实现了.mmap(),其中kzalloced 10Kb缓冲区用remap_pfn_range重新映射,问题仍然存在 不幸的是,我在网上没有发现任何类似的问题,所以我真诚地希望我能在这里找到答案 一些系统信息和内核驱动程序用户空间应用程序代码+运行时日志信息:将映射的Linux字符设备内存注册到CudaHosterRegister会导致参数无效,linux,memory,cuda,mmap,chardev,Linux,Memory,Cuda,Mmap,Chardev,我正试图通过以下方式促进DMACPUGPU数据传输: 1.将我的(专有)设备Linux内核分配的内存映射到用户空间 2.使用cudaHostRegister API函数将后一个(映射内存)注册到Cuda 虽然映射映射到我的设备DMA的用户空间分配内存,然后使用cudaHostRegister注册到Cuda工作正常,但尝试注册“KAlloced”内存会导致cudaHostRegister返回“Invalid Argument”错误 首先,我认为问题在于对齐或我的设备驱动程序复杂的内存池管理,因此我
CUDA : 8.0
OS Dist : Ubuntu 14.04
Kernel : 3.16.0-31-generic
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.26 Driver Version: 375.26 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 770 Off | 0000:83:00.0 N/A | N/A |
| 26% 32C P8 N/A / N/A | 79MiB / 1997MiB | N/A Default |
+-------------------------------+----------------------+----------------------+
字符设备mmap()代码:
测试应用程序代码:
static unsigned long map_mem_size;
int main(int argc, char** argv)
{
int fd;
const char dev_name[] = "/dev/chardev";
void * address = NULL;
long page_off = 0;
cudaError_t cudarc;
switch(argc)
{
case 2:
page_off = atoi(argv[1]) * getpagesize();
break;
default:
page_off = 0;
break;
}
map_mem_size = 2 * getpagesize();
printf("Opening %s file\n", dev_name);
errno = 0;
if(0 > (fd = open(dev_name, O_RDWR) ))
{
printf("Error %d - %s\n", errno, strerror(errno));
}
else
{
printf("About to map %lu bytes of %s device memory\n", map_mem_size, dev_name);
errno = 0;
if(MAP_FAILED == (address = mmap(NULL, map_mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_off)))
{
printf("Error %d - %s\n", errno, strerror(errno));
}
else
{
printf("mapped %s driver 'kmalloc' memory" \
"\n\t\tFirst 8 bytes : %lX" \
"\n\t\tSecond 8 bytes: %lX" \
"\n\t\tLast 8 bytes: %lX\n",
dev_name,
*((unsigned long *)address),
*((unsigned long *)address + 1),
*(unsigned long *)((unsigned char *)address + map_mem_size - sizeof(unsigned long)));
if (cudaSuccess != (cudarc = cudaHostRegister(address, map_mem_size, cudaHostRegisterDefault)))
{
printf("Error: Failed cudaHostRegister: %s, address %p\n", cudaGetErrorString(cudarc), address);
}
}
}
/*Release resources block*/
return EXIT_SUCCESS;
}
运行时调试信息:
用户空间:
./chrdev_test
Opening /dev/chardev file
About to map 8192 bytes of /dev/chardev device memory
mapped /dev/chardev driver 'kmalloc' memory
First 8 bytes : CDFFFFFFFFFFFFAB
Second 8 bytes: AB000000000000EF
Last 8 bytes: EF0000000C0000AA
Error: Failed cudaHostRegister: invalid argument
Unmapping /dev/chardev file
Closing /dev/chardev file
内核空间(tail-f/var/log/syslog):
谢谢你。成功了强>
- 完整答案见:
- 内存块长度超过2页(>8K)时出现问题 与Cuda合作
尤尔。@Robert Crovella这就是重点!如果你mmap任何用户区文件,它工作正常,当我mmap内核内存时,问题就会出现。我99%确定你不能使用mmap进行此操作。事实上,我已得到纠正,注册时(普通)文件的
mmap
似乎不正常work@talonmies这很奇怪,据我所知,大多数v4l2驱动程序在内核中分配内存,如果你是对的,没有办法通过CudahosterRegister来提升他们的数据,在这种情况下,除了我之外的其他人也会遇到同样的问题,但我在网上找不到任何关于这一点的记忆…@Talonmes在任何情况下,请你更具体一点,即:为什么不可能?除了将userland分配的内存映射到驱动程序和Cuda之外,还有什么替代方案?
./chrdev_test
Opening /dev/chardev file
About to map 8192 bytes of /dev/chardev device memory
mapped /dev/chardev driver 'kmalloc' memory
First 8 bytes : CDFFFFFFFFFFFFAB
Second 8 bytes: AB000000000000EF
Last 8 bytes: EF0000000C0000AA
Error: Failed cudaHostRegister: invalid argument
Unmapping /dev/chardev file
Closing /dev/chardev file
[ 4814.119537] [chardev] chardev.c, chdv_mmap, line 292:MEM_CHUNK_SIZE 4096, pages_per_buf 1, vsize 8192 vma->vm_pgoff 0
[ 4814.119538] [chardev] chardev.c, chdv_mmap, line 311:PFN : 16306184
[ 4814.119543] [chardev] chardev.c, chdv_mmap, line 330:Mapped 'kzalloced' buffer
[ 4814.119543] First 8 bytes: CDFFFFFFFFFFFFAB
[ 4814.119543] Second 8 bytes: AB000000000000EF
[ 4814.119543] Last 8 bytes: EF0000000C0000AA