Ale*_*lex 7 cuda gpgpu memory-mapping pci-e gpudirect
我们知道:http://en.wikipedia.org/wiki/IOMMU#Advantages
IOMMU可以支持外围存储器分页.使用PCI-SIG PCIe地址转换服务(ATS)页面请求接口(PRI)扩展的外设可以检测并发出对内存管理器服务的需求.
但是当我们使用CUDA> = 5.0的nVidia GPU时,我们可以使用RDMA GPUDirect,并且知道:
http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#how-gpudirect-rdma-works
传统上,使用CPU的MMU作为内存映射I/O(MMIO)地址,将BAR窗口等资源映射到用户或内核地址空间.但是,由于当前的操作系统没有足够的机制来在驱动程序之间交换MMIO区域,因此NVIDIA内核驱动程序会导出函数以执行必要的地址转换和映射.
http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#supported-systems
从PCI设备的角度来看,GPUDirect的RDMA当前依赖于所有物理地址是相同的.这使它与IOMMU不兼容,因此必须禁用它们才能使RDUD for GPUDirect正常工作.
如果我们将CPU-RAM分配并映射到UVA,如下所示:
#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
int main() {
// Can Host map memory
cudaSetDeviceFlags(cudaDeviceMapHost);
// Allocate memory
unsigned char *host_src_ptr = NULL;
cudaHostAlloc(&host_src_ptr, 1024*1024, cudaHostAllocMapped);
std::cout << "host_src_ptr = " << (size_t)host_src_ptr << std::endl;
// Get UVA-pointer
unsigned int *uva_src_ptr = NULL;
cudaHostGetDevicePointer(&uva_src_ptr, host_src_ptr, 0);
std::cout << "uva_src_ptr = " << (size_t)uva_src_ptr << std::endl;
int b; std::cin >> b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们在Windwos7x64中得到了相同的指针,这意味着cudaHostGetDevicePointer()
什么都不做:
host_src_ptr = 68719476736
uva_src_ptr = 68719476736
它是什么意思"在驱动程序之间交换MMIO区域的充分机制",这意味着什么机制,以及为什么我不能通过使用虚拟地址通过PCIe访问BAR的物理区域来使用IOMMU - 另一个通过PCIe的内存映射设备?
这是否意味着RDMA GPUDirect始终只运行物理地址(在CPU的物理地址空间中),但为什么我们发送到与CPU的虚拟地址空间中的简单指针uva_src_ptr
相同的内核函数host_src_ptr
?
dat*_*boi 10
IOMMU非常有用,因为它提供了一组映射寄存器.它可以安排任何物理内存出现在设备可访问的地址范围内,并且它也可以使物理上分散的缓冲区看起来与设备相邻.这对于试图访问nVidia GPU的原始物理偏移的第三方PCI/PCI-Express卡或远程机器来说并不好,因为这可能导致实际上没有访问预期的内存区域或者禁止/限制这样的访问. IOMMU部门的卡片基础.这必须被禁用,因为
" 从PCI设备的角度来看,RDUD for GPUDirect目前依赖于所有物理地址都是相同的."
-nVidia,rDMA和GPUDirect的设计注意事项
当驱动程序尝试利用CPU的MMU并映射内存映射I/O(MMIO)的区域以在内核空间中使用时,它们通常会将返回的地址从内存映射保留到自身.因为每个驱动程序都在其自己的上下文或命名空间内运行,所以在nVidia的驱动程序和其他希望支持rDMA + GPUDirect的第三方供应商的驱动程序之间交换这些映射将非常困难,并且会产生特定于供应商的解决方案(甚至可能是产品) - 如果第三方产品的驱动程序差异很大,则特定.此外,今天的操作系统目前没有任何好的解决方案来交换驱动程序之间的MMIO映射,因此nVidia导出了几个允许第三方驱动程序从内核空间本身轻松访问这些信息的功能.
nVidia强制使用"物理寻址"通过rDMA为GPUDirect访问每张卡.这大大简化了使用该机器的物理寻址方案将数据从一台计算机移动到远程系统的PCI-Express总线的过程,而不必担心与虚拟寻址相关的问题(例如,将虚拟地址解析为物理地址).每张卡都有一个物理地址,可以在此偏移处访问; 只有少量逻辑必须添加到试图执行rDMA操作的第三方驱动程序.此外,这些32位或64位基址寄存器是标准PCI配置空间的一部分,因此只需读取它的BAR就可以轻松获得卡的物理地址,而不必获得nVidia驱动程序获得的映射地址附在卡上.nVidia的通用虚拟寻址(UVA)负责将上述物理地址映射到用户空间应用程序的看似连续的内存区域,如下所示:
这些内存区域进一步分为三种类型:CPU,GPU和FREE,这些都在此处记录.
回到您的使用案例:由于您处于用户空间,因此您无法直接访问系统的物理地址空间,而您使用的地址可能是nVidia的UVA提供给您的虚拟地址.假设之前没有进行任何分配,您的内存分配应该位于偏移量+ 0x00000000,这将导致您看到GPU本身的相同偏移量.如果你要分配第二个缓冲区,我想你会看到这个缓冲区在第一个缓冲区结束后立即启动(在1 MB分配的情况下,从GPU 的基本虚拟地址偏移+ 0x00100000 ).
但是,如果您在内核空间,并且正在为公司的卡编写驱动程序以将rDMA用于GPUDirect,则可以使用系统的BIOS和/或OS分配给GPU的32位或64位物理地址. rDMA数据直接进出GPU本身.
此外,值得注意的是,并非所有DMA引擎实际上都支持传输的虚拟地址 - 实际上,大多数需要物理地址,因为从DMA引擎处理虚拟寻址会变得复杂(第7页),因此许多DMA引擎都缺乏支持为了这.
但是,要回答帖子标题中的问题:nVidia目前仅支持内核空间中 rDMA + GPUDirect的物理寻址.对于用户空间的应用程序,你将永远使用nVidia的UVA,这是在CPU的虚拟地址空间提供给您的GPU的虚拟地址.
关于您的应用程序,这里是您可以为rDMA操作执行的过程的简化细分:
cuPointerGetAttribute(...)
获取P2P令牌; 这些令牌与CUDA上下文中的内存有关.cuPointerGetAttribute(...)
nvidia_p2p_get_pages(...)
,nvidia_p2p_put_pages(...)
,和nvidia_p2p_free_page_table(...)
.可以在此处找到对此过程的更深入的解释.
归档时间: |
|
查看次数: |
3311 次 |
最近记录: |