CUDA和固定(页面锁定)内存根本没有页面锁定?

时间:2014-11-12 14:05:13

标签: c++ linux memory cuda

当我需要固定(页面锁定)内存时,我试着弄清楚CUDA(或OpenCL实现)是否说实话。

我尝试cudaMallocHost并查看/proc/meminfoMlockedUnevictable,两者都保持为0且永不上升(/proc/<pid>/status报告{{1也作为0)。我使用VmLck页锁定内存,值按预期上升。

这种行为的两个可能原因可能是:

  1. 我没有从CUDA API获取页面锁定内存,而cudaSuccess是假的
  2. CUDA绕过用于页面锁定内存的操作系统计数器,因为CUDA对Linux内核有一定的魔力
  3. 所以实际问题是:当我使用CUDA分配页面锁定内存时,为什么我不能从操作系统获取页面锁定内存的值?

    此外:如果不是mlock/proc/meminfo,我在哪里可以获得正确的值?

    谢谢!

    系统: Ubuntu 14.04.01 LTS; CUDA 6.5; Nvidida Driver 340.29; Nvidia Tesla K20c

2 个答案:

答案 0 :(得分:11)

看起来CUDA 6.5下的固定分配器正在使用带有MAP_FIXED的mmap()。虽然我不是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)       = 16
mmap(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正好是一千兆字节,即与请求的1048576 * 1024相同)

审核mmap的{​​{3}},我们有:

  

address给出映射的首选起始地址。 NULL表示没有首选项。此地址上的任何先前映射都将自动删除。除非您使用MAP_FIXED标志,否则您提供的地址仍可能会更改。

因此,假设mmap命令成功,请求的虚拟地址将被修复,这可能是有用的,但不是整个故事。

正如我所提到的,我不是操作系统专家,对我而言,这个系统调用究竟是什么产生“固定”映射/分配并不明显。可能是MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS的组合以某种方式创建了固定的底层分配,但我没有找到任何证据支持这一点。

基于description,似乎即使mlock()页面也无法满足DMA活动的需要,这是CUDA中固定主机页面的主要目标之一。因此,似乎其他东西提供了实际的“固定”(即保证底层物理页面总是驻留在内存中,并且它们的虚拟到物理映射不会改变 - 后者可能是由MAP_FIXED完成以及任何机制保证底层物理页面不以任何方式移动。)

这种机制显然不使用mlock(),因此mlock的页面在之前和之后都不会改变。但是我们期望映射统计数据发生变化,如果我们对上面程序产生的out1.txt和out2.txt进行区分,我们会看到(摘录):

< Mapped:            87488 kB
---
> Mapped:          1135904 kB

差异大约是一千兆字节,即所请求的“固定”内存量。

答案 1 :(得分:3)

页面锁定可能意味着不同的含义。对于用户空间应用程序,通常意味着将页面保留在内存中以避免页面错误:

“通过mlock()之类的调用已被锁定到内存中的页面必须始终物理存在于系统的RAM中。从表面上看,锁定的页面因此在被应用程序访问时绝不会导致页面错误但是没有什么要求锁定页面始终存在于同一位置;如果需要,内核可以自由移动锁定页面。” [1]

请注意,这些锁定的页面仍然可以移动,不适合I / O设备访问。

相反,页面锁定的另一种概念称为固定。固定页面保持相同的物理映射。需要此功能的驱动程序通常会直接执行此操作,并绕过锁定页面记帐。 cudaMallocHost几乎可以肯定使用cuda驱动程序以这种方式固定页面。

更多信息,请参见下面的[1]。

[1] https://lwn.net/Articles/600502/