CUDA是否将内存固定为零拷贝?

时间:2014-02-06 18:40:03

标签: cuda

固定内存应该可以提高主机到设备的传输速率(api引用)。但是我发现我不需要调用cuMemcpyHtoD来让内核访问这些值,或者cuMemcpyDtoA让主机读回值。我认为这不会起作用,但确实如此:

__global__ void testPinnedMemory(double * mem)
{
    double currentValue = mem[threadIdx.x];
    printf("Thread id: %d, memory content: %f\n", threadIdx.x, currentValue);
    mem[threadIdx.x] = currentValue+10;
}

void test() 
{
    const size_t THREADS = 8;
    double * pinnedHostPtr;
    cudaHostAlloc((void **)&pinnedHostPtr, THREADS, cudaHostAllocDefault);

    //set memory values
    for (size_t i = 0; i < THREADS; ++i)
        pinnedHostPtr[i] = i;

    //call kernel
    dim3 threadsPerBlock(THREADS);
    dim3 numBlocks(1);
    testPinnedMemory<<< numBlocks, threadsPerBlock>>>(pinnedHostPtr);

    //read output
    printf("Data after kernel execution: ");
    for (int i = 0; i < THREADS; ++i)
        printf("%f ", pinnedHostPtr[i]);    
    printf("\n");
}

输出:

Data after kernel execution: 10.000000 11.000000 12.000000 13.000000 14.000000 15.000000 16.000000 17.000000
Thread id: 0, memory content: 0.000000
Thread id: 1, memory content: 1.000000
Thread id: 2, memory content: 2.000000
Thread id: 3, memory content: 3.000000
Thread id: 4, memory content: 4.000000
Thread id: 5, memory content: 5.000000
Thread id: 6, memory content: 6.000000
Thread id: 7, memory content: 7.000000

我的问题是:

  • 固定内存零拷贝?我以为只有映射的固定内存是零拷贝。
  • 如果是零拷贝,为什么要有明确的方法将其映射到设备(cudaHostAlloc并使用cudaHostAllocMapped选项)

我正在使用CUDA Toolkit 5.5,Quadro 4000,驱动程序设置为TCC模式,编译选项sm_20,compute_20

2 个答案:

答案 0 :(得分:9)

  

恭喜!您正在使用较新的CUDA版本遇到2.x计算能力+ TCC + 64位操作系统功能:)

阅读其余内容以了解更多信息!

首先是CUDA教给我们的一个小理论总结:

  • 固定内存不是零复制,因为GPU无法访问它(它没有映射到其地址空间中),而是用于有效地从主机传输到GPU。它是页面锁定(有价值的内核资源)内存,与可分页的普通内存相比具有一些性能优势。

  • 固定零拷贝内存是页锁定内存(通常分配有cudaHostAllocMapped标志),自映射到其地址空间后,GPU也会使用该内存。 / p>

为什么你在没有明确指定的情况下从设备访问从主机分配的内存?

查看CUDA 4.0(及更高版本)的发行说明:

  
      
  • (Windows和Linux)添加了对统一虚拟地址空间的支持。
  •   
     

现在支持64位且计算2.0及更高版本功能的设备   在主机和所有设备之间共享一个统一的地址空间。   这意味着用于访问主机上的内存的指针是   与用于访问设备内存的指针相同。因此,   可以直接从其指针值查询存储器的位置;   无需指定存储器复制的方向。

总结一下:如果你的卡是2.0+(它是:https://developer.nvidia.com/cuda-gpus),你运行的是64位操作系统,而在Windows上你有一个TCC模式,你自动使用主机和设备之间的UVA Unified Virtual Addressing 。这意味着:使用类似零拷贝的访问自动增强代码。

这也在段落“主机分配的主机内存的自动映射”中的CUDA documentation for the current version

答案 1 :(得分:5)

映射内存是一种固定内存。它是在您固定内存并传递cudaHostAllocMapped标志时创建的。 然而,即使您已指定cudaHostAllocDefault,在某些情况下内存也会被“映射”。我相信TCC模式与64位操作系统相结合足以满足“自动映射”功能所需的环境。

核心问题是UVA是否有效。在你的情况下,它是。

关于为什么具有显式功能的问题,它适用于UVA无效的情况(例如在32位主机操作系统中)。

来自documentation

(当UVA生效时):

  

主机分配的主机内存的自动映射

     

使用cudaMallocHost()通过所有设备分配的所有主机内存   始终可以从所有设备直接访问cudaHostAlloc()   支持统一寻址。无论如何都是这种情况   是否标志cudaHostAllocPortable和cudaHostAllocMapped   是指定的。指针值,通过它分配主机内存   可以在支持统一的所有设备上的内核中访问   寻址与该内存的指针值相同   在主机上访问。没有必要打电话   cudaHostGetDevicePointer()获取这些设备的指针   分配。