CUDA线性内存分配
概述:线性存储器可以通过cudaMalloc()、cudaMallocPitch()和cudaMalloc3D()分配
1、1D线性内存分配

1 cudaMalloc(void**,int) //在设备端分配内存
2 cudaMemcpy(void* dest,void* source,int size,enum direction) //数据拷贝
3 cudaMemcpyToSymbol //将数据复制到__constant__变量中,或者__device__变量中
4 cudaMemcpyFromSynbol //同上相反
5 cudaFree() //内存释放
6 cudaMemset() //内存初始化

注意:主机和设备间的数据交换会自动同步,而设备与设备却不会,需要使用cudaThreadSynchronize()
2、2D线性内存分配
2.1 分配
1 cudaMallocPitch( void** devPtr,size_t* pitch,size_t widthInBytes,size_t height ) //在线性内存中分配二维数组,width的单位是字节,而height单位是数据类型
c语言申请2维内存时,一般是连续存放的。a[y][x]存放在第y*widthofx*sizeof(元素)+x*sizeof(元素)个字节。
但在cuda的global memory访问中,从256字节对齐的地址(addr=0, 256, 512, ...)开始的连续访问是最有效率的。这样,为了提高内存访问的效率,有了cudaMallocPitch函数。cudaMallocPitch函数分配的内存中,数组的每一行的第一个元素的开始地址都保证是对齐的。因为每行有多少个数据是不确定的,widthofx*sizeof(元素)不一定是256的倍数。故此,为保证数组的每一行的第一个元素的开始地址对齐,cudaMallocPitch在分配内存时,每行会多分配一些字节,以保证widthofx*sizeof(元素)+多分配的字节是256的倍数(对齐)。这样,上面的y*widthofx*sizeof(元素)+x*sizeof(元素)来计算a[y][x]的地址就不正确了。而应该是y*[widthofx*sizeof(元素)+多分配的字节]+x*sizeof(元素)。而函数中返回的pitch的值就是widthofx*sizeof(元素)+多分配的字节。说明:widthInBytes作为输入参数,应该是widthofx*sizeof(元素);这样的话,复制内容时也要作相应的修改。
2.2 访问
1 T* pElement = (T*)((char*)BaseAddress + Row * pitch) + Column; //元素访问方式
cudaMallocPitch()以*pitch的形式返回间距,即所分配存储器的宽度,以字节为单位。间距用作存储器分配的一个独立参数,用于在2D数组内计算地址。
2.3 拷贝
1 cudaMemcpy2D( void* dst,size_t dpitch,const void* src,size_t spitch,size_t width,size_t height,enum cudaMemcpyKind kind )
这里需要特别注意width与pitch的区别,width是实际需要拷贝的数据宽度而pitch是2D线性存储空间分配时对齐的行宽,而当数据传递发生在设备与主机之间时,主机端pitch==width.
综上我们可以看到,CUDA下对二维线性空间的访问是不提供多下标支持的,访问时依然是通过计算偏移量得到,不同的地方在于使用pitch对齐后非常利于实现coalesce访问
例:下面的代码分配了一个尺寸为width*height的二维浮点数组,同时演示了怎样在设备代码中遍历数组元素

1 // Host code
2 int width = 64, height = 64;
3 float* devPtr;
4 int pitch;
5 cudaMallocPitch((void**)&devPtr, &pitch, width * sizeof(float), height);
6 MyKernel<<<100, 512>>>(devPtr, pitch, width, height);
7 // Device code
8 __global__ void MyKernel(float* devPtr, int pitch, int width, int height){
9 for (int r = 0; r < height; ++r) {
10 float* row = (float*)((char*)devPtr + r * pitch);
11 for (int c = 0; c < width; ++c) {
12 float element = row[c];
13 }
14 }
15 }

3、3D线性内存
1 cudaError_t cudaMalloc3D(
2 struct cudaPitchedPtr * pitchedDevPtr,
3 struct cudaExtent extent
4 )
例:下面的代码分配了一个尺寸为width*height*depth的三维浮点数组,同时演示了怎样在设备代码中遍历数组元素

1 // Host code
2 cudaPitchedPtr devPitchedPtr;
3 cudaExtent extent = make_cudaExtent(64, 64, 64);
4 cudaMalloc3D(&devPitchedPtr, extent);
5 MyKernel<<<100, 512>>>(devPitchedPtr, extent);
6 // Device code
7 __global__ void MyKernel(cudaPitchedPtr devPitchedPtr, cudaExtent extent) {
8 char* devPtr = devPitchedPtr.ptr;
9 size_t pitch = devPitchedPtr.pitch;
10 size_t slicePitch = pitch * extent.height;
11 for (int z = 0; z < extent.depth; ++z) {
12 char* slice = devPtr + z * slicePitch;
13 for (int y = 0; y < extent.height; ++y) {
14 float* row = (float*)(slice + y * pitch);
15 for (int x = 0; x < extent.width; ++x) { float element = row[x];
16 }
17 }
18 }

CUDA线性内存分配的更多相关文章
- 【CUDA 基础】5.1 CUDA共享内存概述
title: [CUDA 基础]5.1 CUDA共享内存概述 categories: - CUDA - Freshman tags: - CUDA共享内存模型 - CUDA共享内存分配 - CUDA共 ...
- CUDA -- 内存分配
CUDA可以认为是一个由软件和硬件构成的并行计算系统,其依赖于GPU的并行计算单元,CUDA有类C的API,方便程序编写.其依赖于CPU和GPU的异构体系,通过在CPU上串行执行环境初始化.内存分配. ...
- CUDA 纹理内存
原文链接 1.概述 纹理存储器中的数据以一维.二维或者三维数组的形式存储在显存中,可以通过缓存加速访问,并且可以声明大小比常数存储器要大的多. 在kernel中访问纹理存储器的操作称为纹理拾取(tex ...
- Linux内核笔记--内存管理之用户态进程内存分配
内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...
- java\c程序的内存分配
JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该 ...
- c++内存分配
[导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...
- 【转】C++ 内存分配(new,operator new)详解
本文主要讲述C++ new运算符和operator new, placement new之间的种种关联,new的底层实现,以及operator new的重载和一些在内存池,STL中的应用. 一 new ...
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...
- Linux内核中常见内存分配函数(二)
常用内存分配函数 __get_free_pages unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) __get_f ...
随机推荐
- IP分片 与 TCP分段的区别 !!!!careful========以及udp中一个包大小究竟为多大合适 ==========三次握手四次挥手细节
首先声明:TCP分片应该称为TCP分段 TCP/IP详解--TCP的分段和IP的分片 分组可以发生在运输层和网络层,运输层中的TCP会分段,网络层中的IP会分片.IP层的分片更多的是为运输层的UDP服 ...
- C++之构造函数、拷贝类型
无参数的构造函数适合没初始化值的初始化对象,而引用拷贝适合创建对象时用另一个对象对其初始化,如果此时用的是浅拷贝则释放一个对象内存时系统会释放2次从而出错(因为它指向同一个内存),深拷贝就不存在这个问 ...
- Trees on the level UVA - 122 (二叉树的层次遍历)
题目链接:https://vjudge.net/problem/UVA-122 题目大意:输入一颗二叉树,你的任务是按从上到下,从左到右的顺序输出各个结点的值.每个结点都按照从根节点到它的移动序列给出 ...
- 性能测试工具Jmeter02-安装配置
安装配置 1.安装配置jdk 2.Jmeter下载地址:http://mirror.bit.edu.cn/apache/jmeter/binaries/ 下载后,解压文件到任意目录,避免在一个有空格的 ...
- 打开/关闭网卡无线WIFI模块
@echo off title ------(Please run as Administrators)Please select------ :begin echo ---------------- ...
- 在Application_Error获取Asp.Net未处理异常信息
在Application_Error获取Asp.Net未处理异常信息 protected void Application_Error(object sender, EventArgs e) { // ...
- Gradient Boosting算法简介
最近项目中涉及基于Gradient Boosting Regression 算法拟合时间序列曲线的内容,利用python机器学习包 scikit-learn 中的GradientBoostingReg ...
- node搭环境(二)之 bower gulp
前面详细记录了安装node及git,接来下要安装bower,首先创建一个空文件夹bowerandgulp. 步骤:1.安装node.js 2.node里面自带了 npm 3.通过npm 安装cnpm ...
- c++ 控制台输入参数
#include <iostream>#include <string> using namespace std; int main(int argc,char **argv) ...
- [Cuckoo SandBox]注入原理篇
1.LoadExe 接python版本 通过调用LoadExe去加载Dll进行注入 所以先看LoadExe 加载器的功能吧 通过python管道接收到 processID,ThreadID,路径 , ...