导言:
大家都知道CUDA 中PageLocked memory 相比portable memory 有着多种优势:
- 在有front-side bus的系统中,pagelocked memory 所提供的host 与device之间的数据传送速度,快得多。测试结果如图Fig.1 Fig.2所示。
- kernel execution 和 pagelocked memory 与 device memory 间的数据复制可同时进行(具体有待实验)。
- 一些设备(计算能力2.0及以上),pagelocked memory 可以被映射到设备地址空间(mapped memory),从而减少对数据复制的需求,增加程序运行速度,这一项将是本文考察的重点。
当然pageLocked memory 也有缺点,那就是内存如果占用过多将影响程序的运行速度,因为这一块内存被锁定后无法自由分配给其他线程或程序。当然对于主机内存资源足够用的小e来说根本也不成问题(4G)。
Fig.1&2 测试结果来源于SDK中bandwidthTest程序
实验目的:
了解pagelocked memory 与Mapped memory的用法。
实验过程:
1、书写代码:建立基于Mapped pagelocked memory 的应用程序需要以下几步
第一步:
分别创建希望通过GPU处理的数据的host端指针,与设备端指针,在下面程序中为:int* h_pData 与 int* d_pData.
第二步:
通过cudaSetDeviceFlags置"cudaDeviceMapHost"标志。
第三部:
通过cudaHostAlloc函数分配pagelocked memory 给指针“h_pData”。
第四部:
通过cudaHostGetDevicePointer函数将主机内存映射到设备端,并绑定指针“d_pData”。
第五部:
执行kernel程序(注意用d_pData)
第六部:
因为设备主机共用pagelocked memory主机端不用内存传输就可直接显示结果。但也正因为不用内存传输(部分内存传输具有同步功能如:cudaMemcpy,部分异步如:cudaMemoryAsync),kernel会在没运行完之前就返回控制给host,所以要想正常显示结果就要使用cudaThreadSynchronize()函数加以控制。
#include <stdlib.h>
#include <stdio.h>
#include <cutil_inline.h>
#include <cuda.h>
#include <shrUtils.h>
#include <assert.h>
__global__ void cu_arrayDelete(int* arrayIO)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
arrayIO[idx] = arrayIO[idx] - 16;
}
void checkCUDAError(const char *msg)
{
cudaError_t err = cudaGetLastError();
if( cudaSuccess != err) {
printf("Cuda error: %s: %s./n", msg, cudaGetErrorString( err) );
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
int* h_pData;
int* d_pData;
cudaDeviceProp deviceProp;
cudaGetDeviceProperties(&deviceProp, 0);
if(!deviceProp.canMapHostMemory) {
printf("Device %d cannot map host memory!/n");
}
cudaSetDeviceFlags(cudaDeviceMapHost);
checkCUDAError("cudaSetDeviceFlags");
cutilSafeCall(cudaHostAlloc((void**)&h_pData, 512, cudaHostAllocMapped));
cudaHostGetDevicePointer((void **)&d_pData, (void *)h_pData, 0);
for(int i=0; i<128; i++)
{
h_pData[i] = 255;
}
cu_arrayDelete<<<4,32>>>(d_pData);
cudaThreadSynchronize();
for(int i = 0 ; i<128; i++ )
printf("%d/n",h_pData[0]);
while(1);
return 0;
}