为了实现CPU与GPU内存的共享,cuda采用了零拷贝内存,它值固定内存的一种,当然,也就是实际存储空间实在cpu上。

零拷贝内存的延迟高,在进行频繁的读写操作时尽量少用,否则会大大降低性能。

/**创建固定内存映射** flags:   cudaHostAllocDefault:      make cudaHostAlloc same as "cudaMallocHost"*          cudaHostAllocPortable:     函数返回能被所有cuda上下文使用的固定内存,而不仅仅是执行内存分配的那个*          cudaHostAllocWriteCombined:返回写结合的内存,该内存可以在某个系统配置上通过PCIe总线上更快的传输*          cudaHostAllocMapped:       该标志返回映射到的设备内存地址空间的主机内存*/cudaError_t cudaHostAlloc(void **pHost, size_t count, unsigned int flags);
/*** 获取映射得到的固定内存的设备指针*/cudaError_t cudaHostGetDevicePointer(void **pDevice, void *pHost, unsigned int flags);

整体的使用过程:

    size_t nBytes = 2048;float *h_A;h_A = (float *)malloc(nBytes);initialData(h_A, nBytes);cudaHostAlloc((void **)&h_A, nBytes, cudaHostAllocMapped);cudaHostGetDevicePointer((void **)&d_A, (void *)h_A, 0);cudaFreeHost(h_A);

给个完整程序,源码网址: 点击打开链接

#include "../common/common.h"
#include <cuda_runtime.h>
#include <stdio.h>/** This example demonstrates the use of zero-copy memory to remove the need to* explicitly issue a memcpy operation between the host and device. By mapping* host, page-locked memory into the device's address space, the address can* directly reference a host array and transfer its contents over the PCIe bus.** This example compares performing a vector addition with and without zero-copy* memory.*/void checkResult(float *hostRef, float *gpuRef, const int N)
{double epsilon = 1.0E-8;for (int i = 0; i < N; i++){if (abs(hostRef[i] - gpuRef[i]) > epsilon){printf("Arrays do not match!\n");printf("host %5.2f gpu %5.2f at current %d\n", hostRef[i],gpuRef[i], i);break;}}return;
}void initialData(float *ip, int size)
{int i;for (i = 0; i < size; i++){ip[i] = (float)( rand() & 0xFF ) / 10.0f;}return;
}void sumArraysOnHost(float *A, float *B, float *C, const int N)
{for (int idx = 0; idx < N; idx++){C[idx] = A[idx] + B[idx];}
}__global__ void sumArrays(float *A, float *B, float *C, const int N)
{int i = blockIdx.x * blockDim.x + threadIdx.x;if (i < N) C[i] = A[i] + B[i];
}__global__ void sumArraysZeroCopy(float *A, float *B, float *C, const int N)
{int i = blockIdx.x * blockDim.x + threadIdx.x;if (i < N) C[i] = A[i] + B[i];
}int main(int argc, char **argv)
{// set up deviceint dev = 0;CHECK(cudaSetDevice(dev));// get device propertiescudaDeviceProp deviceProp;CHECK(cudaGetDeviceProperties(&deviceProp, dev));// check if support mapped memoryif (!deviceProp.canMapHostMemory){printf("Device %d does not support mapping CPU host memory!\n", dev);CHECK(cudaDeviceReset());exit(EXIT_SUCCESS);}printf("Using Device %d: %s ", dev, deviceProp.name);// set up data size of vectorsint ipower = 10;if (argc > 1) ipower = atoi(argv[1]);int nElem = 1 << ipower;size_t nBytes = nElem * sizeof(float);if (ipower < 18){printf("Vector size %d power %d  nbytes  %3.0f KB\n", nElem, ipower,(float)nBytes / (1024.0f));}else{printf("Vector size %d power %d  nbytes  %3.0f MB\n", nElem, ipower,(float)nBytes / (1024.0f * 1024.0f));}// part 1: using device memory// malloc host memoryfloat *h_A, *h_B, *hostRef, *gpuRef;h_A     = (float *)malloc(nBytes);h_B     = (float *)malloc(nBytes);hostRef = (float *)malloc(nBytes);gpuRef  = (float *)malloc(nBytes);// initialize data at host sideinitialData(h_A, nElem);initialData(h_B, nElem);memset(hostRef, 0, nBytes);memset(gpuRef,  0, nBytes);// add vector at host side for result checkssumArraysOnHost(h_A, h_B, hostRef, nElem);// malloc device global memoryfloat *d_A, *d_B, *d_C;CHECK(cudaMalloc((float**)&d_A, nBytes));CHECK(cudaMalloc((float**)&d_B, nBytes));CHECK(cudaMalloc((float**)&d_C, nBytes));// transfer data from host to deviceCHECK(cudaMemcpy(d_A, h_A, nBytes, cudaMemcpyHostToDevice));CHECK(cudaMemcpy(d_B, h_B, nBytes, cudaMemcpyHostToDevice));// set up execution configurationint iLen = 512;dim3 block (iLen);dim3 grid  ((nElem + block.x - 1) / block.x);sumArrays<<<grid, block>>>(d_A, d_B, d_C, nElem);// copy kernel result back to host sideCHECK(cudaMemcpy(gpuRef, d_C, nBytes, cudaMemcpyDeviceToHost));// check device resultscheckResult(hostRef, gpuRef, nElem);// free device global memoryCHECK(cudaFree(d_A));CHECK(cudaFree(d_B));// free host memoryfree(h_A);free(h_B);// part 2: using zerocopy memory for array A and B// allocate zerocpy memoryCHECK(cudaHostAlloc((void **)&h_A, nBytes, cudaHostAllocMapped));CHECK(cudaHostAlloc((void **)&h_B, nBytes, cudaHostAllocMapped));// initialize data at host sideinitialData(h_A, nElem);initialData(h_B, nElem);memset(hostRef, 0, nBytes);memset(gpuRef,  0, nBytes);// pass the pointer to deviceCHECK(cudaHostGetDevicePointer((void **)&d_A, (void *)h_A, 0));CHECK(cudaHostGetDevicePointer((void **)&d_B, (void *)h_B, 0));// add at host side for result checkssumArraysOnHost(h_A, h_B, hostRef, nElem);// execute kernel with zero copy memorysumArraysZeroCopy<<<grid, block>>>(d_A, d_B, d_C, nElem);// copy kernel result back to host sideCHECK(cudaMemcpy(gpuRef, d_C, nBytes, cudaMemcpyDeviceToHost));// check device resultscheckResult(hostRef, gpuRef, nElem);// free  memoryCHECK(cudaFree(d_C));CHECK(cudaFreeHost(h_A));CHECK(cudaFreeHost(h_B));free(hostRef);free(gpuRef);// reset deviceCHECK(cudaDeviceReset());return EXIT_SUCCESS;
}

CUDA零拷贝内存(zerocopy memory)相关推荐

  1. CUDA Samples: dot product(使用零拷贝内存)

    以下CUDA sample是分别用C++和CUDA实现的点积运算code,CUDA包括普通实现和采用零拷贝内存实现两种,并对其中使用到的CUDA函数进行了解说,code参考了<GPU高性能编程C ...

  2. 理解Netty中的零拷贝(Zero-Copy)机制

    理解Netty中的零拷贝(Zero-Copy)机制 发表于2年前(2014-01-13 15:11)   阅读(10209) | 评论(12) 164人收藏此文章,我要收藏 赞29 12月12日北京O ...

  3. 【Netty】零拷贝(zero-copy)

    目录 1. 零拷贝技术实现 2. 传统读取IO流的操作 2.1 读操作 2.2 写操作 2.3 MMAP+write 2.4 Sendfile 3. 零拷贝应用场景 很多更新的技术在宣传的时候,都会提 ...

  4. Linux Zero-copy零拷贝技术:源码示例

    <Linux Zero-copy零拷贝技术:源码示例> <Linux Zero-copy零拷贝技术全面揭秘> <什么是mmap?零拷贝?DMA?> <Linu ...

  5. Linux I/O原理和零拷贝Zero-copy技术全面揭秘

    目录 导言 计算机存储器 物理内存 虚拟内存 静态重定位 存储器抽象 交换(swapping)技术 虚拟内存技术 用户态和内核态 Linux I/O I/O 缓冲区 I/O 模式 程序控制 I/O 中 ...

  6. Kafka和RocketMQ底层存储:零拷贝技术

    零拷本相关 <[转]零拷贝的实现原理> <[转]零拷贝的实现原理> <搞懂Linux零拷贝,DMA> <通过零拷贝进行有效的数据传输(java.c)> ...

  7. 什么是mmap?零拷贝?DMA?

    <Linux Zero-copy零拷贝技术全面揭秘> <什么是mmap?零拷贝?DMA?> <Linux C语言:用零拷贝技术实现TCP代理(源代码+测试服务端客户端代码 ...

  8. 续说零拷贝(Zero-Copy) - DMA技术

    如果想理解Kafaka为什么这么快,得先看DMA是什么. DMA: 无论 I/O 速度如何提升,比起 CPU,总还是太慢.SSD 硬盘的 IOPS 可以到 2 万.4 万,但是我们 CPU 的主频有 ...

  9. linux dma 拷贝内存数据_原来 8 张图,就可以搞懂「零拷贝」了

    前言 磁盘可以说是计算机系统最慢的硬件之一,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝.直接 I/O.异步 I/O 等等,这些优化的目的就是为了提高系统的吞吐量,另外操 ...

最新文章

  1. 详解虚函数的实现过程之菱形继承(5)
  2. 【推荐】查找一代用户出口Userexit
  3. 技术干货 | 高性能短链设计与实现
  4. RUNOOB python练习题12 找素数问题
  5. spring mvc学习(26):处理数据模型--从表单到controller传输数据
  6. zabbix使用zabbix-java-gateway监控jvm/tomcat性能
  7. SQL Server系统数据库–主数据库
  8. angularjs html编码,怎样使用AngularJS实现base64编码与解码
  9. Ffmpeg 解复用器列表 demuxer_list
  10. Intel RST 和Optane 学习笔记
  11. 爬虫中国天气网数据并可视化
  12. 下列c语言表达式正确,C语言试题-10(含答案
  13. 程序分析与优化 - 6 循环优化
  14. cropper.js 实现裁剪图片并上传(PC端)
  15. 硬实时RTLinux?为Linux打实时preempt_rt补丁
  16. python自制小游戏_教你用Python自制拼图小游戏,一起来制作吧
  17. 关于ExecuteNonQuery()执行成功却返回-1的问题
  18. google账号已停用,此账号的使用方式似乎违反了Google的政策
  19. android lightroom,Lightroom
  20. 系统日志管理——journalctl

热门文章

  1. P1510 精卫填海
  2. java实现文件上传(使用FromData)
  3. 洛谷 [P1265] 公路修建
  4. Hive集成Mysql作为元数据时,提示错误:Specified key was too long; max key length is 767 bytes...
  5. VB.Command()的参数
  6. Ubuntu10.10 Server+Nginx+Django+Postgresql安装步骤
  7. Solaris 10 ftp,telnet,ssh,sendmail
  8. Android2.2缩略图类ThumbnailUtils
  9. 网站策划:如何书写网站的商业计划书
  10. DotNet 学习笔记