CUDA编程:cudaMalloc、cudaHostAlloc和cudaMallocManaged三种方式所创建内存在主机和GPU间传输速度的差异
在上一篇文章《CUDA编程: GPU与CPU之间使用统一内存的完整示例代码》里,为了在主机开辟巨大的内存,只读开放给GPU访问,测试了cudaMallocManaged的用法,并提出了一个疑问,到底CUDA里最传统的内存拷贝cudaMalloc,和显式地在主机创建内存cudaHostAlloc再开放给GPU访问,以及全局内存寻址cudaMallocManaged,这三种方式,哪种在GPU与CPU之间传输数据时,有更高的效率?
为了回答这个问题,于是有了以下对上述三种方式所创建的内存,在主机与设备之间传输速度的比较代码。
先贴测试的结果,显然cudaHostAlloc方式创始的主机内存,共享给设备读取时,效率最高:
$ ./test_mem
[+] 比较cudaMalloc、cudaHostAlloc和cudaMallocManaged三种方式创建的内存数据,在主机和GPU间传输的性能差异....
[1] 使用 cudaMalloc 创建[128.00]MB内存空间并从主机传输到GPU 100次耗时: 802.2 ms
传输速度: 15956.9 (MB/s)
[2] 使用 cudaMalloc 创建[128.00]MB内存空间并从GPU传输到主机100次耗时: 1486.6 ms
传输速度: 8610.4 (MB/s)
[3] 使用 cudaHostAlloc 创建[128.00]MB内存空间并从主机传输到GPU 100次耗时: 515.6 ms
传输速度: 24827.8 (MB/s)
[4] 使用 cudaHostAlloc 创建[128.00]MB内存空间并从GPU传输到主机100次耗时: 509.2 ms
传输速度: 25136.0 (MB/s)
[5] 使用 cudaMallocManaged 创建[128.00]MB内存空间并从主机传输到GPU 100次耗时: 1161.2 ms
传输速度: 11022.7 (MB/s)
[6] 使用 cudaMallocManaged 创建[128.00]MB内存空间并从GPU传输到主机100次耗时: 1064.9 ms
传输速度: 12019.5 (MB/s)
结论是显著的,cudaHostAlloc有着最高的性能,速度是另外两方式的二至三倍。
以下是测试程序 cuda_mem_cpy.cu 完整的源代码:
/*******************************************************************************************************************
* 文件名 cuda_mem_cpy.cu
* 编译: nvcc -o test_uvm uvm_test.cu
* 功能:比较cudaMalloc、cudaHostAlloc和cudaMallocManaged三种方式创建的内存数据,在主机和GPU间传输的性能差异
* author: Ryan
********************************************************************************************************************/
#include <iostream>
#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <device_launch_parameters.h>
#define SIZE (32*1024*1024)
using namespace std;
//------------------------------------------------------------------------------------------------------------------
void HANDLE_ERROR(cudaError_t cuda_error_code){
if(cuda_error_code != cudaSuccess)
printf("[E] CUDA返回错误: %s\n", cudaGetErrorString(cuda_error_code));
}
//------------------------------------------------------------------------------------------------------------------
// 测试 cudaMalloc 方法
float cuda_malloc_test(int size, bool up) {
cudaEvent_t start, stop;
int *a, *dev_a;
float elapsedTime;