CUDA页锁定内存(Pinned Memory)
对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)的更多相关文章
- 6.1 CUDA: pinned memory固定存储
CPU和GPU内存交互 在CUDA编程中,内存拷贝是非常费时的一个动作. 从上图我们可以看出:1. CPU和GPU之间的总线bus是PCIe,是双向传输的. 2. CPU和GPU之间的数据拷贝使用DM ...
- 如何启用“锁定内存页”选项 (Windows)
默认情况下,禁用 Windows 策略"锁定内存页"选项.必须启用此权限才能配置地址窗口化扩展插件 (AWE).此策略将确定哪些帐户可以使用进程将数据保留在物理内存中,从而阻止系统 ...
- [SPDK/NVMe存储技术分析]015 - 理解内存注册(Memory Registration)
使用RDMA, 必然关系到内存区域(Memory Region)的注册问题.在本文中,我们将以mlx5 HCA卡为例回答如下几个问题: 为什么需要注册内存区域? 注册内存区域有嘛好处? 注册内存区域的 ...
- linux内核剖析(十一)进程间通信之-共享内存Shared Memory
共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程 ...
- 内存管理 - MEMORY POOL
内存池优势: 效率高,频繁的new和delete效率低下 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片 防止内存泄露 内存池设计思路: 内存池可以根据实际需要,设计成不同的样子.下面是针对 ...
- 内存分配器 (Memory Allocator)
对于大多数开发人员而言,系统的内存分配就是一个黑盒子,就是几个API的调用.有你就给我,没有我就想别的办法. 来UC前,我就是这样觉得的.实际深入进去时,才发现这个领域里也是百家争鸣.非常热闹.有操作 ...
- 从五大结构体,带你掌握鸿蒙轻内核动态内存Dynamic Memory
摘要:本文带领大家一起剖析了鸿蒙轻内核的动态内存模块的源代码,包含动态内存的结构体.动态内存池初始化.动态内存申请.释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列九 动态内存Dyna ...
- Android 内存管理 &Memory Leak & OOM 分析
转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...
- 关于Linux的缓存内存 Cache Memory详解<转>
转自 http://www.ha97.com/4337.html PS:前天有童鞋问我,为啥我的Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存 ...
随机推荐
- 再记AE与AO的区别与联系
原文地址:转:ArcObjects与ArcEngine作者:梦游 ArcObjects(简称AO),一般都是指ArcGIS Desktop版本的组件开发集,即需要安装ArcGIS桌面版软件后才能安 ...
- FTP 访问的形式
主要是扼要的列举一下访问的方式,不涉及太具体的内容.大家可以在百度上搜索一下具体的操作方法. 主要有: 1. 网页浏览器中输入 ftp://192.168.0.111的形式. 2. 资源管理器中输入f ...
- 动态规划求解序列问题(LIS、JLIS)
1. 最长递增子序列 不要求位置连续:要求大小严格递增(strictly increasing) 穷举法解题 首先以每个数字为单位分割寻找最长递增子序列: int lis(const vector&l ...
- 9.11 Binder系统_分层
1.Binder系统过程分析,情景分析 server提供服务 (1)addService(服务名称,xxx)执行后会导致binder驱动在server的内核空间为服务创建一个binder_node结构 ...
- SDWebImage使用
SDWebImage这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. 将SDWebImage类库添加入工程时,一定 ...
- 利用VS安装项目打包软件的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 昨天摸索了一下,发现使用VS安装项目来打包软件还是挺方便的. 1. 创建一个安装项目工程,如下图: 2. 设置工程属性 ...
- 分类算法简介 分类: B10_计算机基础 2015-03-09 11:08 257人阅读 评论(0) 收藏
一.决策树 决策树是用于分类和预测的主要技术之一,决策树学习是以实例为基础的归纳学习算法,它着眼于从一组无次序.无规则的实例中 推理出以决策树表示的分类规则.构造决策树的目的是找出属性和类别间的关系, ...
- 编译Valgrind arm交叉编译
1. 下载源码: http://valgrind.org/downloads/valgrind-3.9.0.tar.bz2 2. 加压缩: mkdir sw cd sw tar zxf valgr ...
- USB 3.0规范中译本 第10章 集线器,主机下行口以及设备上行口规范
本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 本章描述USB 3.0 集线器的体系结构要求.本章还描述主机下行口和集线器下行口之间功能性的不同之处,以及设 ...
- JS和CSS压缩部署,提高访问效率
一直想把项目中的js和css压缩下,今天终于搞定了. 先说说几个注意的问题,目标影响着你对应的解决办法:1.压缩后的文件,是否要直接覆盖旧的文件2. 单个压缩文件重命名,还是整个目录换个名字,同时文件 ...