统一内存(unified memory)是一种逻辑上的概念,它既不是显存、也不是主机内存,而是CPU和GPU都可以访问并能保证一致性的虚拟存储器。使用统一内存对硬件有较高的要求:

  • 对于所有功能,GPU架构都必须不低于Kepler架构,主机应用程序必须为64位。
  • 对于一些较新的功能,至少需要Pascal架构的GPU,且主机必须是Linux系统。

使用统一内存编程的优势如下:

  • 统一内存使编程更加简单。不需要手动将数据在主机和设备之间传输,也不需要针对同一组数据定义两个指针并分别分配主机内存和设备内存。对于某个统一内存变量,可以直接从CPU或GPU中访问。
  • 可能会提供比手工移动数据更好的性能。统一内存的底层实现,可能会自动将一部分数据放到离某个处理器更近的位置,比如部分放到显存中,部分放到主存中,从而让相关数据尽量靠近对应的处理器。虽然统一内存机制可以部分地做到这些,但很多情况下还是需要手动给编译器一些提示,这部分功能需要Linux系统且不低于Pascal架构的GPU。
  • 允许GPU在使用统一内存的情况下,进行超量分配。超出GPU内存额度的部分可能存放在主机上。该功能也要求Linux系统且不低于Pascal架构的GPU。

动态分配统一内存使用的CUDA运行时API函数如下:

cudaError_t cudaMallocManaged(void **devPtr, size_t size, unsigned int flags = cudaMemAttachGlobal);

相比于cudaMalloc函数,该函数多个一个可选参数flags,其默认值cudaMemAttachGlobal代表分配的全局内存可由任何设备通过任何CUDA流进行访问。只能在主机端使用该函数分配统一内存,不能在核函数中使用该函数。分配了统一内存的变量既可以被设备访问,也可以被主机访问。从核函数的角度看,统一内存和普通设备内存在使用上没有任何区别,性能也基本相同。使用动态统一内存改写的数组相加例程如下:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <cmath>
#include <cstdio> const double EPSILON = 1.0e-15;
const double a = 1.23;
const double b = 2.34;
const double c = 3.57; void __global__ add(const double* x, const double* y, double* z)
{
const int n = blockDim.x * blockIdx.x + threadIdx.x;
z[n] = x[n] + y[n];
} void check(const double* z, const int N)
{
bool has_error = false;
for (int n = 0; n < N; ++n)
{
if (fabs(z[n] - c) > EPSILON)
{
has_error = true;
}
}
printf("%s\n", has_error ? "Has errors" : "No errors");
} int main(void)
{
const int N = 100000000;
const int M = sizeof(double) * N;
double* x, * y, * z;
cudaMallocManaged((void**)&x, M);
cudaMallocManaged((void**)&y, M);
cudaMallocManaged((void**)&z, M); for (int n = 0; n < N; ++n)
{
x[n] = a;
y[n] = b;
} const int block_size = 128;
const int grid_size = N / block_size;
add << <grid_size, block_size >> > (x, y, z); cudaDeviceSynchronize();
check(z, N); cudaFree(x);
cudaFree(y);
cudaFree(z);
return 0;
}

统一内存也可以静态分配,只要在修饰符的__device__的基础上再加上修饰符__managed__即可。这样的变量是在任何函数外部定义的,可见范围是所在源文件(更准确地说是所在翻译单元)。官方文档《CUDA C++ Programming Guide》中的示例如下:

__device__ __managed__ int ret[1000];
__global__ void AplusB(int a, int b) {
ret[threadIdx.x] = a + b + threadIdx.x;
}
int main() {
AplusB<<< 1, 1000 >>>(10, 100);
cudaDeviceSynchronize();
for(int i = 0; i < 1000; i++)
printf("%d: A+B = %d\n", i, ret[i]);
return 0;
}

《CUDA编程:基础与实践》读书笔记(5):统一内存编程的更多相关文章

  1. 《Essential C++》读书笔记 之 基于对象编程风格

    <Essential C++>读书笔记 之 基于对象编程风格 2014-07-13 4.1 如何实现一个class 4.2 什么是Constructors(构造函数)和Destructor ...

  2. 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理

    二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...

  3. 《编写可维护的javascript》读书笔记(中)——编程实践

    上篇读书笔记系列之:<编写可维护的javascript>读书笔记(上) 上篇说的是编程风格,记录的都是最重要的点,不讲废话,写的比较简洁,而本篇将加入一些实例,因为那样比较容易说明问题. ...

  4. 《jQuery基础教程》读书笔记

    最近在看<jQuery基础教程>这本书,做了点读书笔记以备回顾,不定期更新. 第一章第二章比较基础,就此略过了... 第三章 事件 jQuery中$(document).ready()与j ...

  5. 《Java并发编程的艺术》读书笔记:一、并发编程的目的与挑战

    发现自己有很多读书笔记了,但是一直都是自己闷头背,没有输出,突然想起还有博客圆这么个好平台给我留着位置,可不能荒废了. 此文读的书是<Jvava并发编程的艺术>,方腾飞等著,非常经典的一本 ...

  6. 【读书笔记】C#高级编程 第十三章 异步编程

    (一)异步编程的重要性 使用异步编程,方法调用是在后台运行(通常在线程或任务的帮助下),并不会阻塞调用线程.有3中不同的异步编程模式:异步模式.基于事件的异步模式和新增加的基于任务的异步模式(TAP, ...

  7. 【读书笔记】iOS-GCD-多线程编程

    一,现在一个物理的CPU芯片实际上有64个(64核)CPU,如果1个CPU核虚拟为两个CPU核工作,那么一台计算机上使用多个CPU核就是理所当然的事了.尽管如此,“1个CPU核执行的CPU命令为一条无 ...

  8. 《深入java虚拟机》读书笔记之Java内存区域

    前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,主要是方便之后进行复习. 运行时数据区域 Java虚拟 ...

  9. 《深入分析Java Web技术内幕》读书笔记之JVM内存管理

    今天看JVM的过程中收获颇丰,但一想到这些学习心得将来可能被遗忘,便一阵恐慌,自觉得以后要开始坚持做读书笔记了. 操作系统层面的内存管理 物理内存是一切内存管理的基础,Java中使用的内存和应用程序的 ...

  10. Java并发编程实践读书笔记(2)多线程基础组件

    同步容器 同步容器是指那些对所有的操作都进行加锁(synchronize)的容器.比如Vector.HashTable和Collections.synchronizedXXX返回系列对象: 可以看到, ...

随机推荐

  1. 解密prompt系列41. GraphRAG真的是Silver Bullet?

    这一章我们介绍GraphRAG范式,算着时间也是该到图谱了,NLP每一轮新模型出来后,往往都是先研究微调,然后各种预训练方案,接着琢磨数据,各种主动学习半监督,弱监督,无监督,再之后就到图谱和对抗学习 ...

  2. 每秒550万亿次算力!打破世界纪录!中国造全球首例纯电驱全尺寸人形机器人!直击全球最快人形机器人“天工”The world's first purely electric humanoid robot

    地址: https://www.youtube.com/watch?v=uRc-885NpD4

  3. dotnet core微服务框架Jimu ~ 会员注册微服务

    提供会员注册服务,用户必须注册成会员才能享受应用提供的服务,如浏览和发布新闻, 但有些服务又需要指定角色的会员才能操作,如所有会员都可以浏览新闻,只有管理员(admin)角色的会员才可以发布新闻. 有 ...

  4. 关于C++当中的“模板函数”

    本人C++草鸟,在工作当中遇到了这个问题,就简单做个记录.

  5. 根据不同的dpi 媒体查询

    /* 默认样式 */ .element { width: 100px; height: 100px; background-color: blue; } /* 当设备像素比为1.5时,调整.eleme ...

  6. 【昌哥IT课堂】MySQL8.4.0新特性:FLUSH_PRIVILEGES动态权限细化与隔离[译]

    介绍MySQL 支持 RELOAD 权限.现在,想象一个数据库用户被授予了 RELOAD 权限,这允许该用户在系统上执行 FLUSH PRIVILEGES 语句.假设该用户意外地执行了另一个强大的语句 ...

  7. [昌哥IT课堂]|欢迎 MySQL 9.0,回顾 Oracle 在 8.0 版中的管理(译)

    对于新兴技术和社区的管理是相对容易的.经过 29 年发展,MySQL 已成为全球数百万用户中使用最广泛且备受信任的开源数据库之一.在这一规模的社区领导中可能存在复杂性.我们努力寻求稳定和创新的平衡,为 ...

  8. (Python基础教程之六)Python中的关键字

    Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...

  9. Java 编程的动态性,第 1 部分: 类和类装入

    研究类以及 JVM 装入类时所发生的情况 这一有关 Java 编程动态方面的新的系列文章研究了执行 Java 应用程序时幕后所发生的事情.企业 Java专家 Dennis Sosnoski 提供了 J ...

  10. ClickHouse之基础使用

    [安装] [YUM] 1.添加官方存储库 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://packag ...