2012-10-20 33 views
2

我正试图寻找我程序中的一个错误。它产生cudaMalloc在不同的CPU线程上返回相同的内存地址

[vaio:10404] Signal: Segmentation fault (11) 
[vaio:10404] Signal code: Address not mapped (1) 
[vaio:10404] Failing at address: 0x210000 
[vaio:10405] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0) [0x7fa7857ffcb0] 
[vaio:10405] [ 1] /lib/x86_64-linux-gnu/libc.so.6(+0x14fe20) [0x7fa785580e20] 
[vaio:10405] [ 2] /usr/lib/libcuda.so.1(+0x1b1f49) [0x7fa78676bf49] 

0x210000是住在GPU内存中的地址。我没有统一的地址空间(由于卡片限制:sm_12)。

通过mpiexec -n 2运行程序时发生此问题。也就是说,我启动了2个CPU进程,都在相同的(!)GPU上创建了自己的上下文(仅安装了1个GPU)。就像这样:

cuInit(0); 
cuDeviceGet(&cuDevice, 0); // get device number 0 
cuCtxCreate(&cuContext, 0, cuDevice); // create context 
cuMemAlloc(&mem , size); // allocate memory pool (hundreds of MB) 

(这是在这里简单 - 所有CUDA调用检查错误返回)

我使用这个设置很成功很长一段时间,现在(多个主机进程共享相同的GPU) 。但是,那是使用CUDA运行时API的时候。现在,我切换到驱动程序API。

为了追捕这件事,我把上面代码的mem转储出来。原来,cuMemAlloc返回的内存地址在两个进程中都是相同的!这让我想起了我。这里转储出:

process 0: allocate internal buffer: unaligned ptr = 0x210000 aligned ptr = 0x210000 
process 1: allocate internal buffer: unaligned ptr = 0x210000 aligned ptr = 0x210000 

立即我用我的旧代码(运行时API)检查,从来没有这样的问题。原来它报告两个进程(共享相同的设备)相同的内存地址。这从未引起我的注意。

我觉得这很难相信。只是为了清楚:两个进程都要求设备内存有cudaMalloc(运行时API)和cuMalloc(驱动程序API)(大卡上有400MB),并且两个进程都返回相同的地址? 我相信没有一个进程正在前进很多并且已经释放内存,因此第一个进程可以重用相同的内存,因为第一个进程已经终止。不,这个内存用作内存池来为后续的内存分配提供服务,并且它们之间有很多同步点。池在程序终止时被释放。

任何人都知道如何将相同的指针值(内存地址)报告给两个进程,但在GPU上这是指不同的内存? (因为它执行的计算是正确的,如果内存池重叠,情况就不会这样)。据我所知,这是不可能的。我错过了什么?

+0

伟大的问题,+1。 –

+1

talonmies是对的。这与在两个不同的CPU进程中获取相同地址没有区别。 – ArchaeaSoftware

回答

4

您错过了虚拟寻址的概念。

每个CPU线程都有自己的CUcontext,每个CUcontext都有自己的GPU 虚拟地址空间。从API返回的地址是虚拟的,主机驱动程序和/或设备将虚拟地址转换为GPU内存中的绝对地址。有大量证据表明GPU具有专门用于此目的的TLB。

+0

这将假设成功的'cuMalloc'可能在不同的CPU线程上返回相同的值。而且,由于虚拟到实际地址映射是在专用硬件的帮助下完成的(如您所说),所以无法从应用程序的角度告诉真实地址。 – ritter

+0

@Frank:是的,这就是一些GPU API使用不透明缓冲区对象来表示内存分配而不是裸指针的原因。该应用程序并不能够或需要非常了解GPU地址的含义。 – talonmies

相关问题