当前位置: 首页 > 面试题库 >

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

林曦之
2023-03-14
问题内容

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

我尝试cudaMallocHost查看了和的/proc/meminfo值,Mlocked并且Unevictable都保持为0且从未上升(/proc/<pid>/status报告VmLck也为0)。我曾经使用mlock过页面锁定内存,并且值按预期上升。

因此,此行为的两个可能原因可能是:

  1. 我没有从CUDA API获得页面锁定的内存,而cudaSuccess是伪造的
  2. 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)       = 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恰好是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,即请求的“固定”内存量。



 类似资料:
  • 我从这个链接(Mifare Ultralight C Lock)获得了参考,使Mifare Ultralight标签上的所有页面都是只读的。 我可以在Android上成功地在Mi的Ultralight标签上写入消息。现在我想锁定第4到7页(或任何特定页面)。上面的链接只显示了如何锁定所有页面。我如何锁定特定页面? 此代码锁定所有页面:

  • 由于网页被锁定,我在chrome中使用了view-source:https://www.gearhungy.com/best-monitor-arm/并手动删除了锁定它的代码。 现在,我想使用请求来获取BS4的html内容,但我正在获取下面的编码数据,但我现在无法破解这个字节代码3个小时。 <类“字节”>

  • 设定画面锁定用的通行码。启动PS Vita电源或自待命模式恢复时需输入通行码,以防止第三者非法利用。 设定通行码 一开始需先设定称为通行码的密码。解除画面锁定时需输入通行码。 轻触[加密]>[画面锁定],输入4位数字。 若忘记通行码,需初始化PS Vita。请小心切勿遗忘已设定的通行码,亦不要让第三者知道您的通行码。 解除锁定时确认通行码 若轻触方格启用设定,启动PS Vita电源或自待命模式恢复

  • 根据postgres文档第13.3.2节 除了表锁和行锁之外,页级共享/独占锁还用于控制对共享缓冲池中表页的读/写访问。这些锁在读取或更新行后立即释放。应用程序开发人员通常不需要关心页面级锁,但为了完整起见,此处提到了它们。 我的理解是,我不需要担心我的事务是否足够大,以至于它们可以锁定足够长的行,以至于T1在P1上的R1上有一个锁,并且想要锁定P2上的R2,但不能这样做,因为T2在P2上的R3上

  • 这是我的代码,我想我的页脚是静态的在我的html页面底部,我如何修复它?

  • 问题内容: 我在这里思考:如果您有2个线程执行需要同步的FAST操作,那么非阻塞方法不是比阻塞/上下文切换方法更快/更好的方法吗? 非阻塞的意思是: while(true){如果(checkAndGetTheLock())中断;} 如果您有太多线程在锁中循环,我唯一想到的就是饥饿(CPU耗尽)。 如何平衡一种方法与另一种方法? 问题答案: 以下是 Java Concurrency in Pract