CUDA编程学习笔记 之 页锁定内存(固定内存Pinned Memory)

主机内存分为 可分页内存(Pagable)页锁定内存(固定内存Pinned Memory)

CPU向GPU传输数据时是通过直接内存访问(DMA,Direct Memory Access)传输的。
但是主机虚拟内存中分配的数据在物理内存中是随时可能被移动的,所以当数据在可分页内存时,系统随时可能会移动数据,此时将该数据传输给GPU时,需要将可分页内存复制到一块“临时的”页锁定内存,然后再从这块“临时的页锁定内存“复制到GPU
因此使用页锁定内存会一定程度上加快数据在GPU与CPU之间的传输速度,甚至会加快一倍

但是,页锁定内存是占用系统的物理内存的,并不能交换到磁盘上,当机器的物理内存比较少时程序运行会受到影响

因此页锁定内存在不再使用时需要立刻释放

分配页锁定内存:
①由cudaHostAlloc( )来进行分配
②在opencv的GPU模块中,申请固定内存存储图片时,可以使用下面的函数来申请

CudaMem img_host(cols,rows, CV_8UC1, CudaMem::ALLOC_PAGE_LOCKED)

释放页锁定内存:

cudaFreeHost ( )

下面是一个将图片传到页锁定内存的应用示例,其中还有相应的CUDA测试运行时间的代码

float feature_match_pl()
{
	//数据导入
	Mat img1 = imread("D:/Images/14.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	CV_Assert(!img1.empty());//CV_Assert()若括号中的表达式值为false,则返回一个错误信息。
	Mat img2 = imread("D:/Images/15.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	CV_Assert(!img2.empty());

	//耗时统计
	cudaEvent_t start, stop;
	float elapsedTime;
	cudaEventCreate(&start);
	cudaEventCreate(&stop);

	//计时开始
	cudaEventRecord(start, 0);

	//申请页锁定内存
	CudaMem img1_host(img1.cols, img1.rows, CV_8UC1, CudaMem::ALLOC_PAGE_LOCKED);
	CudaMem img2_host(img2.cols, img2.rows, CV_8UC1, CudaMem::ALLOC_PAGE_LOCKED);

	memcpy(img1_host.datastart, img1.datastart, img1_host.cols * img1_host.rows);
	memcpy(img2_host.datastart, img2.datastart, img2_host.cols * img2_host.rows);

	GpuMat img1_gpu, img2_gpu;

	//图像传输到设备
	img1_gpu.upload(img1_host);
	CV_Assert(!img1_gpu.empty());
	img2_gpu.upload(img2_host);
	CV_Assert(!img2_gpu.empty());

    //释放
	cudaFreeHost(&img1_host);
	cudaFreeHost(&img2_host);

	//计时结束
	cudaEventRecord(stop, 0);
	cudaEventSynchronize(stop);
	cudaEventElapsedTime(&elapsedTime, start, stop);

	cudaEventDestroy(start);
	cudaEventDestroy(stop);

	return (float)elapsedTime / 1000;
}


int main(int argc, char* argv[])
{
	//检查CUDA能否正常使用
	if (getCudaEnabledDeviceCount() == 0) {
		cerr << "此OpenCV编译的时候没有启用CUDA模块" << endl;
		return -1;
	}
	//输出所使用的GPU信息
	//cv::gpu::printShortCudaDeviceInfo(cv::gpu::getDevice());
	//for (int i = 0; i < 3; i++)
	//{
		float time2 = feature_match_pl();
		printf("使用页锁定内存耗时: %.6f s\n", time2);
	//}
	waitKey(0);
	return 0;
}

你可能感兴趣的:(CUDA编程)