原文链接

简单描述一下自己要做的事情:(1)CPU三维的vector--->(2)CPU三维数组--->(3)转换到GPU中的三维数组--->(4)转换到CPU中的三维数组,而其中问题主要出在第3、4步。

主要是没有理解一个问题,那就是“cuda的各种拷贝一定要是内存连续的”。而自己在申请三维数组的时候用的是new或者malloc,这种在申请一维数组的时候是连续的,但是在申请多维数组就会出现不连续,因此在这里犯了致命错误。

http://hpcbbs.it168.com/thread-7366-1-1.html这个帖子给了很好的建议,“vector<vector<float> > 并不是二维数组吧,它只是实现了二维数组的操作(比如[][]).内存是不连续的。要用cudaMemcpy还是得定义 float 2darray[N][M] 或者 直接 float *2darray = new float(M*N);”。反正就是这样,纸上得来终觉浅,自己多亲身力为一下。

 #include "example1.cuh"
#include "Struct.h"
/************************************************************************/
/* 转换成设备可以识别的 */
/************************************************************************/
void InitCPUData(DataMatrix &datamatrix,std::vector<std::vector<std::vector<float > > > vec3D1,
std::vector<std::vector<std::vector<float > > > vec3D2,int width,int height,int depth)
{
int i,j,k;
for (i=;i<depth;i++)
{
for (j=;j<height;j++)
{
for (k=;k<width;k++)
{
datamatrix.Mat3D1[i][j][k]=vec3D1[i][j][k];
datamatrix.Mat3D2[i][j][k]=vec3D2[i][j][k];
}
}
}
} /************************************************************************/
/* 分配并且赋值 */
/************************************************************************/
__host__ void AllocDataAndVal(DataStruct &datastruct,DataMatrix datamatrix,int width,int height,int depth)
{
//分配内存
cudaExtent extent=make_cudaExtent(sizeof(float)*,,);
cutilSafeCall(cudaMalloc3D(&(datastruct.Vec3D1),extent));
cutilSafeCall(cudaMalloc3D(&(datastruct.Vec3D2),extent));
//赋值
cudaMemcpy3DParms Parms3D1={};
cudaMemcpy3DParms Parms3D2={};
Parms3D1.dstPtr=datastruct.Vec3D1;
Parms3D2.dstPtr=datastruct.Vec3D2;
Parms3D1.srcPtr=make_cudaPitchedPtr((void*)datamatrix.Mat3D1,width*sizeof(float),width,height);
Parms3D2.srcPtr=make_cudaPitchedPtr((void*)datamatrix.Mat3D2,width*sizeof(float),width,height);
Parms3D1.extent=extent;
Parms3D2.extent=extent;
Parms3D1.kind=cudaMemcpyHostToDevice;
Parms3D2.kind=cudaMemcpyHostToDevice;
cudaMemcpy3D(&Parms3D1);
cudaMemcpy3D(&Parms3D2);
} /************************************************************************/
/* 核函数 */
/************************************************************************/
__global__ void kernel(DataStruct datastruct,int width,int height,int depth) //实现类中两个数组的相加,保持到第一个数组中
{
char* devPtr1=(char*)datastruct.Vec3D1.ptr; //起始地址
char* devPtr2=(char*)datastruct.Vec3D2.ptr;
int pitch=datastruct.Vec3D1.pitch; //pitch,相当于宽度
int SlicePitch=pitch*height;
//用线程
int xid=threadIdx.x;
int yid=threadIdx.y;
int zid=threadIdx.z;
if (xid<width&&yid<height&&zid<depth)
{
((float*)((char*)(devPtr1+zid*SlicePitch)+yid*pitch))[zid]=((float*)((char*)(devPtr1+zid*SlicePitch)+yid*pitch))[zid]+
((float*)((char*)(devPtr2+zid*SlicePitch)+yid*pitch))[zid];
}
} /************************************************************************/
/* 返回到主机上 */
/************************************************************************/
__host__ void GPU2CPU(DataStruct &datastruct,DataMatrix datamatrix, int width,int height,int depth)
{
cudaExtent extent=make_cudaExtent(sizeof(float)*,,);
cudaMemcpy3DParms Parms3D1={};
cudaMemcpy3DParms Parms3D2={};
Parms3D1.srcPtr=datastruct.Vec3D1;
Parms3D2.srcPtr=datastruct.Vec3D2;
Parms3D1.dstPtr=make_cudaPitchedPtr((void*)datamatrix.Mat3D1,width*sizeof(float),width,height);
Parms3D2.dstPtr=make_cudaPitchedPtr((void*)datamatrix.Mat3D2,width*sizeof(float),width,height);
Parms3D1.extent=extent;
Parms3D2.extent=extent;
Parms3D1.kind=cudaMemcpyDeviceToHost;
Parms3D2.kind=cudaMemcpyDeviceToHost;
cudaMemcpy3D(&Parms3D1);
cudaMemcpy3D(&Parms3D2); }

主函数:

 // 说明:在cu中host和device的虽然写在一起,但是是分开编译的,这个在一起只是形式上的。如果函数前面有__global__由主机调用设备执行,__device__设备调用设备执行,__host__主机调用主机执行。其分别对应三种形式为核函数、核函数中的函数、一般函数。

 #include <iostream>
#include <vector>
#include <algorithm>
#include "example1.cuh"
#include "Struct.h" int main()
{
int i,j,k;
int width=;
int height=;
int depth=;
std::vector<std::vector<std::vector<float > > > vec3D1(width); //建立6*7*8的三维数组,范文depth-height-width
std::vector<std::vector<std::vector<float > > > vec3D2(width); vec3D1.resize(depth);
vec3D2.resize(depth);
for (i=;i<depth;i++)
{
vec3D1[i].resize(height);
vec3D2[i].resize(height);
for (j=;j<height;j++)
{
vec3D1[i][j].resize(width);
vec3D2[i][j].resize(width);
for (k=;k<width;k++)
{
vec3D1[i][j][k]=i+j+k;
vec3D2[i][j][k]=i*j*k;
}
}
} //////////////////////////////////////////////////////////////////////////
//将数据转换成设备可以接受的形式,为赋值做准备,这个是在主机上进行
DataMatrix datamatrix;
InitCPUData(datamatrix,vec3D1,vec3D2,width,height,depth); //////////////////////////////////////////////////////////////////////////
//给设备分配内存并且赋值,这个是在设备上进行
DataStruct datastruct;
AllocDataAndVal(datastruct,datamatrix,width,height,depth); //////////////////////////////////////////////////////////////////////////
//调用核函数
dim3 dimBlock(,,);
kernel<<<,dimBlock>>>(datastruct,width,height,depth); //////////////////////////////////////////////////////////////////////////
//返回到主机,并显示出来
GPU2CPU(datastruct,datamatrix,width,height,depth);
for (i=;i<depth;i++)
{
for (j=;j<height;j++)
{
for (k=;k<width;k++)
{
printf("%f ",datamatrix.Mat3D1[i][j][k]);
}
printf("\n");
}
printf("\n");
printf("\n");
} //释放空间
cudaFree(&(datastruct.Vec3D1));
cudaFree(&(datastruct.Vec3D2)); }

cuda数组的拷贝的更多相关文章

  1. PHP 数组的拷贝是按值传递 or 按引用传递

    在记忆中 PHP 简单变量的拷贝是按值传递,数组和对象的拷贝是按引用传递,即通过引用来实现. 简单变量和对象好理解: <?php // 简单变量的拷贝 $a = 'human'; $b = $a ...

  2. CUDA零内存拷贝 疑问考证

    今天思考了一下CUDA零内存拷贝的问题,感觉在即将设计的程序中会派上用场,于是就查了一下相关信息. 以下是一些有帮助的链接: cuda中的零拷贝用法--针对二维指针 cuda中的零拷贝用法--针对一维 ...

  3. java-IO流-字符流-FileReader、FileWriter、自定义小数组的拷贝、BufferedReader、BufferedWriter、readLine()和newLine()方法、LineNumberReader、使用指定的码表读写字符

    ###21.01_IO流(字符流FileReader) * 1.字符流是什么     * 字符流是可以直接读写字符的IO流     * 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要 ...

  4. javascript数组操作(创建、元素删除、数组的拷贝)

    这篇文章主要介绍了javascript数组操作,包括创建.元素的访问.元素删除.数组的拷贝等操作,还有其它示例,需要的朋友可以参考下 1.数组的创建 复制代码 代码如下: var arrayObj = ...

  5. 【CUDA开发】CUDA面内存拷贝用法总结

    [CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...

  6. JS中数组的拷贝方法

    之前在写一个vue的计算属性时,大概是这样: computed: { updateList () { let newList = this.List /*do something*/ return n ...

  7. java数组的拷贝和扩容

    1.拷贝arraycopy方法 // 拷贝:arraycopy方法 // arraycopy // 第一个参数:原数组 // 第二个参数:原数组元素的起始位置 // 第三个参数:目标数组 // 第四个 ...

  8. Java一维与二维数组的拷贝与排序

    Java一维与二维数组的拷贝与排序 目录 Java一维与二维数组的拷贝与排序 Arrays.sort() 一维数组升序排序 二维数组按行升序排序 二维数组按列升序排序 Java中的数组 Java中数组 ...

  9. js 数组的拷贝

    在js中,数组Array是引用类型,直接将数组赋值给一个变量名,二者所指向的地址是一样的. 所以直接复制数组会产生意想不到的结构. 要想解决拷贝一个数组但是对副本的修改不影响原来的数组,有以下方式: ...

随机推荐

  1. RequireJS -Javascript模块化(一、简介)

    1.认识RequireJS RequireJs官网(http://requirejs.org/)的描述: RequireJS is a JavaScript file and module loade ...

  2. java编程--04比较几个常用的日期时间相关类的区别

    第一篇,介绍日期的比较 第二篇,介绍日期的格式化 第三篇,介绍关于日期常用的计算 第四篇,比较几个常用的日期时间相关类的区别 第五篇,jdk9对日期类进行了更新,写一些i自己的学习心得. 下面以一组思 ...

  3. 源码剖析Linux epoll实现机制及Linux上惊群

    转载:https://blog.csdn.net/tgxallen/article/details/78086360 看源码是对一个技术认识最直接且最有效的方式了,之前用Linux Epoll做过一个 ...

  4. Murano Weekly Meeting 2016.08.02

    Meeting time: 2016.August.02 1:00~2:00 Chairperson:  Valerii Kovalchuk, from Mirantis Meeting summar ...

  5. 给用户添加sodu权限

    vim /etc/sudoers 进入编辑模式,找到这一 行:"root ALL=(ALL) ALL"在起下面添加"xxx ALL=(ALL) ALL"(这里的 ...

  6. Linux kernel rbtree

    Linux kernel rbtree 因编写内核模块时需要用到rbtree来记录异步request,研究分析了一下kernel rbtree的使用方法,记录于此.本文主要参考了内核文档rbtree. ...

  7. 设置checkbox只读

    1.checkbox没有readonly属性,所以在checkbox添加readonly属性是没有作用的. <input type="checkbox" readonly=& ...

  8. MVC之ViewData.Model

    在MVC中前台Razor视图呈现数据的方式不止一种.举个简单的Demo,我们要把用户信息呈现给人民. 一.ViewData.Model的使用,先简单写一下Razor @model   User---- ...

  9. jsp smartupload学习

    smartupload 是jsp中用于上传文件的组件, 其特点如下: 1.使用简单.在JSP文件中仅仅书写三五行java代码就可以搞定文件的上传或下载,方便. 2.能全程控制上传.利用jspSmart ...

  10. 总结spring

    通过对spring的学习 什么是spring Spring是一个基于IOC和AOP的结构J2EE系统的框架 IOC 反转控制 是Spring的基础,Inversion Of Control 简单说就是 ...