为什么CUDA Kernel可以访问主机内存,cudaMallocHost后还需调用cudaMemcpy?
为什么CUDA Kernel直接访问主机内存没有报错
你代码里的主机内存是通过cudaMallocHost分配的页锁定(pinned)主机内存,加上你使用的是支持统一虚拟寻址(UVA)的CUDA环境(64位操作系统+开普勒架构及以上的NVIDIA GPU,目前绝大多数主流CUDA设备都满足这个条件),驱动会自动统一编址主机和设备的地址空间,设备端Kernel拿到页锁定内存的指针可以直接寻址访问,因此不会触发非法地址访问的报错。
如果你换成普通malloc分配的可分页主机内存直接传入Kernel访问,就会出现段错误类的运行报错。
为什么调用cudaMallocHost后很多程序依然会执行cudaMemcpy
核心原因是性能差异,直接在Kernel中访问页锁定主机内存的效率远低于先拷贝到显存再访问:
- 带宽差距:当前消费级/数据中心级GPU的显存带宽普遍在数百GB/s到数TB/s级别,而PCIe 4.0 x16的带宽仅为32GB/s,PCIe 5.0 x16也只有64GB/s,显存带宽是PCIe总线的10~100倍。
- 延迟与缓存:Kernel访问显存可以利用GPU片上的L1、L2缓存大幅降低访问延迟,而直接访问主机内存需要走PCIe总线,每次访问延迟是显存访问的数十倍,且离散的随机访问会进一步放大带宽损耗。
- 复用收益:如果同一份数据需要被Kernel多次访问,仅执行一次
cudaMemcpy拷贝到显存,后续所有访问都走高速显存,整体收益远高于每次访问都跨PCIe请求主机内存。
你当前的测试代码数据量极小(仅6464的int数组,总大小16KB),性能差异无法体现,如果把数组规模放大到10241024甚至更大,就能观测到两种实现的明显性能差距。
内容的提问来源于stack exchange,提问作者coordinate
相关产品推荐
相关产品推荐

