博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CUDA学习(九十三)
阅读量:5915 次
发布时间:2019-06-19

本文共 2121 字,大约阅读时间需要 7 分钟。

简化GPU编程:

存储空间的统一意味着主机和设备之间不再需要显式存储器传输。 在托管内存空间中创建的任何分配都会自动迁移到需要的位置。
程序以两种方式之一分配托管内存:通过cudaMallocManaged()例程,它在语义上类似于cudaMalloc(); 或者通过定义一个全局的__managed__变量,这个变量在语义上类似于__device__变量。 这些文件的精确定义见本文后面。
在具有计算能力6.x的设备的支持平台上,Unified Memory将使应用程序能够使用默认系统分配器分配和共享数据。 这允许GPU在不使用特殊分配器的情况下访问整个系统虚拟内存。
以下代码示例说明了如何使用托管内存可以更改写入主机代码的方式。 首先,一个没有统一内存利益的简单程序:

__global__ void AplusB(int *ret, int a, int b) {    ret[threadIdx.x] = a + b + threadIdx.x;}int main() {    int *ret;    cudaMalloc(&ret, 1000 * sizeof(int));    AplusB << < 1, 1000 >> >(ret, 10, 100);    int *host_ret = (int *)malloc(1000 * sizeof(int));    cudaMemcpy(host_ret, ret, 1000 * sizeof(int), cudaMemcpyDefault);    for (int i = 0; i<1000; i++)        printf("%d: A+B = %d\n", i, host_ret[i]);    free(host_ret);    cudaFree(ret);    return 0;}

第一个示例将GPU上的两个数字与每个线程ID结合在一起,并将数值返回到数组中。 如果没有托管内存,则需要用于返回值的主机和设备端存储(在本例中为host_ret和ret),因为两者之间使用cudaMemcpy()进行显式拷贝。

将此与程序的统一内存版本进行比较,该版本允许从主机直接访问GPU数据。 注意cudaMallocManaged()例程,它返回一个有效来自主机和设备代码的指针。 这允许在没有单独的host_ret副本的情况下使用ret,极大地简化和减小了程序的大小。

__global__ void AplusB(int *ret, int a, int b) {    ret[threadIdx.x] = a + b + threadIdx.x;}int main() {    int *ret;    cudaMalloc(&ret, 1000 * sizeof(int));    AplusB << < 1, 1000 >> >(ret, 10, 100);    int *host_ret = (int *)malloc(1000 * sizeof(int));    cudaMemcpy(host_ret, ret, 1000 * sizeof(int), cudaMemcpyDefault);    for (int i = 0; i<1000; i++)        printf("%d: A+B = %d\n", i, host_ret[i]);    free(host_ret);    cudaFree(ret);    return 0;}

最后,语言集成允许直接引用GPU声明的__managed__变量,并在使用全局变量时进一步简化程序。

__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;}

请注意,缺少显式的cudaMemcpy()命令以及返回数组ret在CPU和GPU上都可见的事实。

对主机和设备之间的同步值得评论。 请注意,在非托管示例中,同步cudaMemcpy()例程用于同步内核(即等待它完成运行)并将数据传输到主机。 统一内存示例不会调用cudaMemcpy(),因此在主机程序可以安全地使用GPU输出之前需要明确的cudaDeviceSynchronize()。
这里的另一种方法是设置环境变量CUDA_LAUNCH_BLOCKING = 1,确保所有内核的启动都是同步完成的。 这通过消除所有显式同步来简化代码,但显然对整个执行行为具有更广泛的影响。
timg

转载地址:http://cewvx.baihongyu.com/

你可能感兴趣的文章
各种链接
查看>>
我的友情链接
查看>>
《Spring实战》第四版读书笔记 第一章 Spring之旅
查看>>
那些年,一起学的Java 2-4
查看>>
RedHat已更改其开源许可规则
查看>>
redis集群搭建
查看>>
LNMP架构 (Ⅱ)——nginx相关配置、nginx代理
查看>>
神级python程序员只需要一个公众号,再也不会错过重要资讯
查看>>
双十一流量洪峰 支撑阿里核心业务的云数据库揭秘
查看>>
OSChina 周一乱弹 ——程序员跟产品经理撕逼必须掌握的套路
查看>>
Linux系统启动流程详解
查看>>
Magento(CE1.X)自带模块解析五
查看>>
Factory Method模式 (一)
查看>>
代码整洁之道-第9章-单元测试-读书笔记
查看>>
C++ ssd5 12 optional exercise2
查看>>
如何调用带返回值类型的函数
查看>>
linux网络编程涉及的函数
查看>>
数据表的相关操作
查看>>
POJ 2594 Treasure Exploration(最小可相交路径覆盖)题解
查看>>
数据挖掘十大经典算法
查看>>