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 ...
随机推荐
- 转 Django中的Form
https://www.cnblogs.com/chenchao1990/p/5284237.html Form 一.使用Form Django中的Form使用时一般有两种功能: 1.生成html标签 ...
- IP分片 与 TCP分段的区别 !!!!careful========以及udp中一个包大小究竟为多大合适 ==========三次握手四次挥手细节
首先声明:TCP分片应该称为TCP分段 TCP/IP详解--TCP的分段和IP的分片 分组可以发生在运输层和网络层,运输层中的TCP会分段,网络层中的IP会分片.IP层的分片更多的是为运输层的UDP服 ...
- team foundation server 工具的使用
1.打开TFS工具点击创建集合,填写集合名称,下一步,按照步骤一步一步的往下操作. 2.创建完集合以后,打开VS工具,如下图,在主页上左键选择新建团队项目. 3.选择团队项目,然后选择新建的项目集合和 ...
- speex编译
首先去官网 https://www.speex.org/downloads/ 下载解压 将include.libspeex文件夹复制到自己新建工程的jni目录下 speex有关的类 package c ...
- [转]jQuery调用ASPX返回json
本文转自:http://www.cnblogs.com/fire-phoenix/archive/2009/11/13/1614146.html 本文介绍如何在ASP.NET(ASP.NET/AJAX ...
- [引]雅虎日历控件 Example: Two-Pane Calendar with Custom Rendering and Multiple Selection
本文转自:http://yuilibrary.com/yui/docs/calendar/calendar-multipane.html This example demonstrates how t ...
- JS arguments转array
JS arguments转array? Array.prototype.slice.call(arguments)
- 单元测试-Junit-Mockit-PowerMock
0. Junit5 1. Junit4 //手动命令行测试 java -cp /usr1/junit:/usr1/cdncms/lib/* org.junit.runner.JUnitCore com ...
- CentOS下NFS服务器配置教程
说明: NFS服务器: 操作系统:CentOS 5.5 IP:192.168.21.160 nfs网络文件服务器共享目录:/data/osyunwei 目录所有者:www(说明:www为nginx运行 ...
- stl::iterator汇总
STL——iterator 一.概述Iterator(迭代器)模式又称Cursor(游标)模式, 根据STL中的分类,iterator包括:Input Iterator:只能单步向前迭代元素,不允许修 ...