CUDA和固定(页面锁定)内存根本没有页面锁定?
我尝试弄清楚当我需要固定(页面锁定)内存时,CUDA(或OpenCL实现)是否能说明问题。
我尝试cudaMallocHost
查看了和的/proc/meminfo
值,Mlocked
并且Unevictable
都保持为0且从未上升(/proc/<pid>/status
报告VmLck
也为0)。我曾经使用mlock
过页面锁定内存,并且值按预期上升。
因此,此行为的两个可能原因可能是:
- 我没有从CUDA API获得页面锁定的内存,而cudaSuccess是伪造的
- CUDA绕开了页面锁定内存的OS计数器,因为CUDA对Linux内核做了一些魔术
所以实际的问题是:当我使用CUDA分配页面锁定的内存时,为什么不能从操作系统中获取页面锁定的内存的值?
另外:如果不能从/proc/meminfo
或从哪里获得正确的值/proc/<pid>/status
?
谢谢!
系统:Ubuntu 14.04.01 LTS; CUDA 6.5; Nvidida驱动程序340.29; 英伟达Tesla K20c
回答:
似乎在引擎盖下的CUDA
6.5上固定的分配器mmap()
与MAP_FIXED一起使用。尽管我不是OS专家,但是这显然具有“固定”内存的作用,即确保其地址永远不变。但是,这不是一个完整的解释。请参阅@Jeff的答案,指出几乎可以肯定的是“缺失的部分”。
让我们考虑一个简短的测试程序:
#include <stdio.h>#define DSIZE (1048576*1024)
int main(){
int *data;
cudaFree(0);
system("cat /proc/meminfo > out1.txt");
printf("*$*before alloc\n");
cudaHostAlloc(&data, DSIZE, cudaHostAllocDefault);
printf("*$*after alloc\n");
system("cat /proc/meminfo > out2.txt");
cudaFreeHost(data);
system("cat /proc/meminfo > out3.txt");
return 0;
}
如果我们使用来运行该程序strace
,并在printf
语句之间摘录输出部分,那么我们将:
write(1, "*$*before alloc\n", 16*$*before alloc) = 16mmap(0x204500000, 1073741824, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, 0, 0) = 0x204500000
ioctl(11, 0xc0304627, 0x7fffcf72cce0) = 0
ioctl(3, 0xc0384657, 0x7fffcf72cd70) = 0
write(1, "*$*after alloc\n", 15*$*after alloc) = 15
(请注意1073741824恰好是1 GB,即与请求的1048576 * 1024相同)
回顾描述的mmap
,我们有:
地址为映射提供了首选的起始地址。NULL不表示首选项。该地址以前的所有映射都将自动删除。您提供的地址可能仍会更改,除非您使用MAP_FIXED标志。
因此,假设mmap
命令成功执行,则请求的虚拟地址将被固定,这可能是有用的,但并不是全部。
正如我提到的,我不是OS专家,对我来说,这个系统调用究竟会创建一个“固定”映射/分配,这对我来说并不明显。可能是MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS
某种方式的组合创建了固定的基础分配,但是我还没有找到任何证据来支持这一点。
根据本文,偶数mlock()
页面似乎无法满足DMA活动的需求,这是CUDA中固定主机页面的主要目标之一。因此,似乎其他方式正在提供实际的“固定”功能(即,保证基础物理页面始终位于内存中,并且它们的虚拟到物理映射不会更改-
后面的内容可能是MAP_FIXED
与任何机制一起完成,都可以确保基础物理页面不会以任何方式移动)。
该机制显然不使用mlock()
,因此之前和之后的锁页面都不会更改。但是,我们期望映射统计信息会发生变化,并且如果将上述程序生成的out1.txt和out2.txt进行比较,我们将看到(摘录):
< Mapped: 87488 kB---
> Mapped: 1135904 kB
差异约为1 GB,即请求的“固定”内存量。
以上是 CUDA和固定(页面锁定)内存根本没有页面锁定? 的全部内容, 来源链接: utcz.com/qa/402226.html