当前位置: 首页 > news >正文

CUDA学习(七)

设备内存:
正如异构编程中提到的那样,CUDA编程模型假设一个由主机和设备组成的系统,每个系统都有自己独立的内存。 内核在设备内存之外运行,因此runtime提供了分配,解除分配和复制设备内存的功能,以及在主机内存和设备内存之间传输数据。
设备内存可以分配为线性内存或CUDA数组。
CUDA数组是不透明的内存布局,针对纹理获取进行了优化。 它们在纹理和表面记忆中被描述。
线性内存在设备上存在于40位地址空间中,因此分开分配的实体可以通过指针相互引用,例如在二叉树。
线性内存通常使用cudaMalloc()进行分配,并使用cudaFree()进行释放,主机内存和设备内存之间的数据传输通常使用cudaMemcpy()完成。 在内核的向量附加代码示例中,向量需要从主机内存复制到设备内存:

// Device code
__global__ void VecAdd(float* A, float* B, float* C, int N)
{
    int i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < N)
        C[i] = A[i] + B[i];
}
// Host code
int main()
{
    int N = ...;
    size_t size = N * sizeof(float);
    // Allocate input vectors h_A and h_B in host memory
    float* h_A = (float*)malloc(size);
    float* h_B = (float*)malloc(size);
    // Initialize input vectors
    ...
        // Allocate vectors in device memory
        float* d_A;
    cudaMalloc(&d_A, size);
    float* d_B;
    cudaMalloc(&d_B, size);
    float* d_C;
    cudaMalloc(&d_C, size);
    // Copy vectors from host memory to device memory
    cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
    // Invoke kernel
    int threadsPerBlock = 256;
    int blocksPerGrid =
        (N + threadsPerBlock - 1) / threadsPerBlock;
    VecAdd << <blocksPerGrid, threadsPerBlock >> >(d_A, d_B, d_C, N);
    // Copy result from device memory to host memory
    // h_C contains the result in host memory
    cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);
    // Free device memory
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);
    // Free host memory
    ...
}

线性内存也可以通过cudaMallocPitch()和cudaMalloc3D()来分配。 建议将这些功能用于分配2维或者3维的数组,因为它确保分配适当地填充以满足器件存储器访问中描述的对齐要求,因此在访问行地址或在2D数组与其他区域之间执行复制时确保最佳性能 的设备内存(使用cudaMemcpy2D()和cudaMemcpy3D()函数)。返回的pitch(或stride)必须用于访问数组元素。以下代码示例分配宽x高二维浮点值数组,并显示如何遍历设备代码中的数组元素:

// Host code
int width = 64, height = 64;
float* devPtr;
size_t pitch;
cudaMallocPitch(&devPtr, &pitch,
    width * sizeof(float), height);
MyKernel << <100, 512 >> >(devPtr, pitch, width, height);
// Device code
__global__ void MyKernel(float* devPtr,
    size_t pitch, int width, int height)
{
    for (int r = 0; r < height; ++r) {
        float* row = (float*)((char*)devPtr + r * pitch);
        for (int c = 0; c < width; ++c) {
            float element = row[c];
        }
    }
}

以下代码示例分配宽度x高度x深度3D浮点数值数组,并显示如何遍历设备代码中的数组元素:

// Host code
int width = 64, height = 64, depth = 64;
cudaExtent extent = make_cudaExtent(width * sizeof(float),
    height, depth);
cudaPitchedPtr devPitchedPtr;
cudaMalloc3D(&devPitchedPtr, extent);
MyKernel << <100, 512 >> >(devPitchedPtr, width, height, depth);
// Device code
__global__ void MyKernel(cudaPitchedPtr devPitchedPtr,
    int width, int height, int depth)
{
    char* devPtr = devPitchedPtr.ptr;
    size_t pitch = devPitchedPtr.pitch;
    size_t slicePitch = pitch * height;
    for (int z = 0; z < depth; ++z) {
        char* slice = devPtr + z * slicePitch;
        for (int y = 0; y < height; ++y) {
            float* row = (float*)(slice + y * pitch);
            for (int x = 0; x < width; ++x) {
                float element = row[x];
            }
        }
    }
}

参考手册列出了用cudaMalloc()分配的线性存储器,用cudaMallocPitch()或cudaMalloc3D()分配的线性存储器,CUDA数组和分配给在全局或常量存储空间中声明的变量的存储器之间复制存储器的所有函数。
以下代码示例说明了通过运行时API访问全局变量的各种方法:

__constant__ float constData[256];
float data[256];
cudaMemcpyToSymbol(constData, data, sizeof(data));
cudaMemcpyFromSymbol(data, constData, sizeof(data));
__device__ float devData;
float value = 3.14f;
cudaMemcpyToSymbol(devData, &value, sizeof(float));
__device__ float* devPointer;
float* ptr;
cudaMalloc(&ptr, 256 * sizeof(float));
cudaMemcpyToSymbol(devPointer, &ptr, sizeof(ptr));

cudaGetSymbolAddress()用于检索指向为全局内存空间中声明的变量分配的内存的地址。 分配的内存大小是通 cudaGetSymbolSize()获得的。
1

相关文章:

  • docker同宿主机容器和不同宿主机容器之间怎么通信?
  • Android自定义搜索框,封装了 历史搜索记录功能和样式
  • VuePress 静态网站生成
  • Android中View内部类MeasureSpec研究
  • Java多线程父子线程关系 多线程中篇(六)
  • 使用Nginx、Nginx Plus抵御DDOS攻击
  • 前嗅ForeSpider中数据浏览界面介绍
  • NPOI 笔记
  • webpy简单入门---1
  • 印刷名片用什么格式的文件好?
  • spring boot + vue + element-ui全栈开发入门——主页面开发
  • 技术胖1-4季视频复习— (看视频笔记)
  • 如何查找Fiori UI上某个字段对应的后台存储表的名称
  • 日志切割
  • Visual Studio 代码折叠快捷键(摘要)
  • CAP理论的例子讲解
  • ESLint简单操作
  • JS题目及答案整理
  • PAT A1017 优先队列
  • Redis 懒删除(lazy free)简史
  • Terraform入门 - 1. 安装Terraform
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • VuePress 静态网站生成
  • vue中实现单选
  • windows下如何用phpstorm同步测试服务器
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 高程读书笔记 第六章 面向对象程序设计
  • 搞机器学习要哪些技能
  • 嵌入式文件系统
  • 新版博客前端前瞻
  • 学习ES6 变量的解构赋值
  • 一些关于Rust在2019年的思考
  • 鱼骨图 - 如何绘制?
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​iOS实时查看App运行日志
  • !!Dom4j 学习笔记
  • #1014 : Trie树
  • (C语言)球球大作战
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (二)fiber的基本认识
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (规划)24届春招和25届暑假实习路线准备规划
  • (十)T检验-第一部分
  • (转)ABI是什么
  • .gitattributes 文件
  • .NET中GET与SET的用法
  • [20150321]索引空块的问题.txt
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [C\C++]读入优化【技巧】
  • [Git 1]基本操作与协同开发
  • [IE6 only]关于Flash/Flex,返回数据产生流错误Error #2032的解决方式
  • [Interview]Java 面试宝典系列之 Java 多线程
  • [JS入门到进阶] 7条关于 async await 的使用口诀,新学 async await?背10遍,以后要考!快收藏