对CUDA架构而言,主机端的内存被分为两种,一种是可分页内存(pageable memroy)和页锁定内存(page-lock或 pinned)。可分页内存是由操作系统API malloc()在主机上分配的,页锁定内存是由CUDA函数cudaHostAlloc()在主机内存上分配的,页锁定内存的重要属性是主机的操作系统将不会对这块内存进行分页和交换操作,确保该内存始终驻留在物理内存中。

GPU知道页锁定内存的物理地址,可以通过“直接内存访问(Direct Memory Access,DMA)”技术直接在主机和GPU之间复制数据,速率更快。由于每个页锁定内存都需要分配物理内存,并且这些内存不能交换到磁盘上,所以页锁定内存比使用标准malloc()分配的可分页内存更消耗内存空间。

页锁定内存的内配、操作和可分页内存的对比:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "iostream"
#include <stdio.h> using namespace std; float cuda_host_alloc_test(int size, bool up)
{
//耗时统计
cudaEvent_t start, stop;
float elapsedTime;
cudaEventCreate(&start);
cudaEventCreate(&stop); int *a, *dev_a; //在主机上分配页锁定内存
cudaError_t cudaStatus = cudaHostAlloc((void **)&a, size * sizeof(*a), cudaHostAllocDefault);
if (cudaStatus != cudaSuccess)
{
printf("host alloc fail!\n");
return -1;
} //在设备上分配内存空间
cudaStatus = cudaMalloc((void **)&dev_a, size * sizeof(*dev_a));
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMalloc failed!\n");
return -1;
} //计时开始
cudaEventRecord(start, 0); for (int i = 0; i < 100; i++)
{ //从主机到设备复制数据
cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(*dev_a), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy Host to Device failed!\n");
return -1;
} //从设备到主机复制数据
cudaStatus = cudaMemcpy(a, dev_a, size * sizeof(*dev_a), cudaMemcpyDeviceToHost);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy Device to Host failed!\n");
return -1;
}
}
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop); cudaFreeHost(a);
cudaFree(dev_a);
cudaEventDestroy(start);
cudaEventDestroy(stop); return (float)elapsedTime / 1000; } float cuda_host_Malloc_test(int size, bool up)
{
//耗时统计
cudaEvent_t start, stop;
float elapsedTime;
cudaEventCreate(&start);
cudaEventCreate(&stop); int *a, *dev_a; //在主机上分配可分页内存
a = (int*)malloc(size * sizeof(*a)); //在设备上分配内存空间
cudaError_t cudaStatus = cudaMalloc((void **)&dev_a, size * sizeof(*dev_a));
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMalloc failed!\n");
return -1;
} //计时开始
cudaEventRecord(start, 0); for (int i = 0; i < 100; i++)
{ //从主机到设备复制数据
cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(*dev_a), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy Host to Device failed!\n");
return -1;
} //从设备到主机复制数据
cudaStatus = cudaMemcpy(a, dev_a, size * sizeof(*dev_a), cudaMemcpyDeviceToHost);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy Device to Host failed!\n");
return -1;
}
}
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop); free(a);
cudaFree(dev_a);
cudaEventDestroy(start);
cudaEventDestroy(stop); return (float)elapsedTime / 1000;
} int main()
{
float allocTime = cuda_host_alloc_test(100000, true);
cout << "页锁定内存: " << allocTime << " s" << endl;
float mallocTime = cuda_host_Malloc_test(100000, true);
cout << "可分页内存: " << mallocTime << " s" << endl;
getchar();
return 0;
}

对比效果,页锁定内存的访问时间约为可分页内存的访问时间的一半:

CUDA页锁定内存(Pinned Memory)的更多相关文章

  1. 6.1 CUDA: pinned memory固定存储

    CPU和GPU内存交互 在CUDA编程中,内存拷贝是非常费时的一个动作. 从上图我们可以看出:1. CPU和GPU之间的总线bus是PCIe,是双向传输的. 2. CPU和GPU之间的数据拷贝使用DM ...

  2. 如何启用“锁定内存页”选项 (Windows)

    默认情况下,禁用 Windows 策略"锁定内存页"选项.必须启用此权限才能配置地址窗口化扩展插件 (AWE).此策略将确定哪些帐户可以使用进程将数据保留在物理内存中,从而阻止系统 ...

  3. [SPDK/NVMe存储技术分析]015 - 理解内存注册(Memory Registration)

    使用RDMA, 必然关系到内存区域(Memory Region)的注册问题.在本文中,我们将以mlx5 HCA卡为例回答如下几个问题: 为什么需要注册内存区域? 注册内存区域有嘛好处? 注册内存区域的 ...

  4. linux内核剖析(十一)进程间通信之-共享内存Shared Memory

    共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程 ...

  5. 内存管理 - MEMORY POOL

    内存池优势: 效率高,频繁的new和delete效率低下 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片 防止内存泄露 内存池设计思路: 内存池可以根据实际需要,设计成不同的样子.下面是针对 ...

  6. 内存分配器 (Memory Allocator)

    对于大多数开发人员而言,系统的内存分配就是一个黑盒子,就是几个API的调用.有你就给我,没有我就想别的办法. 来UC前,我就是这样觉得的.实际深入进去时,才发现这个领域里也是百家争鸣.非常热闹.有操作 ...

  7. 从五大结构体,带你掌握鸿蒙轻内核动态内存Dynamic Memory

    摘要:本文带领大家一起剖析了鸿蒙轻内核的动态内存模块的源代码,包含动态内存的结构体.动态内存池初始化.动态内存申请.释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列九 动态内存Dyna ...

  8. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  9. 关于Linux的缓存内存 Cache Memory详解<转>

    转自 http://www.ha97.com/4337.html PS:前天有童鞋问我,为啥我的Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存 ...

随机推荐

  1. Oracle 中的Interger类型

    引自 wolfAone, oracle有没有integer类型,这种类型的最大值是多少啊. Integer是Number类型的子类型: NUMBER Type You use the NUMBER d ...

  2. (7)Launcher3客制化之,改动单屏幕后,Fix在Hotseat拖动应用删除报错

    改动单屏幕后,在workspace里面拖动图标.到删除button上松开的时候,报错问题. 而且无法再次显示拖动的图标. 拖动松开手时候触发 public void onDropCompleted(f ...

  3. 9.2 Binder系统_驱动情景分析_服务注册过程

    1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...

  4. 【例题3-4 UVA - 340】Master-Mind Hints

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 这里出现了没有在相同位置的只能唯一配对. 就是说 3322 2234 这种情况. 只有3个weak pair. 即key[1]=a[ ...

  5. 魔兽争霸war3心得体会(二):狗转蜘蛛,DK光环+游侠二发

    最近几周,勤奋地在QQ对战平台上,练习war3对战. 10年玩到14年初, 也玩了很多,主要是抱着"随便玩玩"的心态,结果也很显然,可以轻松打赢中等电脑,以及AI不够高的发狂的Hu ...

  6. 解决Eclipse中的卡死现象

    解决Eclipse中的卡死现象 取消验证 windows–>perferences–>validation 把 除了manual 下面的全部点掉,build下只留 classpath de ...

  7. 用IBM WebSphere DataStage进行数据整合: 第 1 部分 分类: H2_ORACLE 2013-08-23 11:20 688人阅读 评论(0) 收藏

    转自:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0602zhoudp/ 引言 传统的数据整合方式需要大量的手工 ...

  8. Session or Cookie?是否需要用Tomcat等Web容器的Session

    Cookie是HTTP协议标准下的存储用户信息的工具,浏览器把用户信息存放到本地的文本文件中. Session是基于Cookie实现的. 2011年4月,武汉群硕面试的时候(实习生),面试官也问过这个 ...

  9. [SCSS] Use Standard Built-in SCSS Functions for Common Operations

    We can use javascript for color and opacity variations, math, list and map logic or to see if someth ...

  10. php汉字字符串长度和截取

    mb_strlen("你好123",'utf-8');//返回5 strlen("你好");//返回几我也不知道,肯定不是2,但你想要2就用上面的 substr ...