原文链接

简单描述一下自己要做的事情:(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. python安装包的时候报错

    python安装包的时候报错 今天兴致勃勃的安装了一个paramiko包,过程很顺利,但是到结尾的时候报错,这就让人不爽了. 所以呢,需要安装一个名为python-dev的软件包. 该软件包包括头文件 ...

  2. oracle 用mybatis生成主键

    oracle主键是不能像mysql一样自动管理的,需要自己手动管理,先生成,再插入. <selectKey keyProperty="id" resultType=" ...

  3. 工作中常用到的sql命令!!!

    一.mysql数据库日常操作.     1.启动mysql:/etc/init.d/mysql start (前面为mysql的安装路径)     2.重启mysql:  /etc/init.d/my ...

  4. IDEA修改git账号及密码的方法

    IDEA修改git账号及密码的方法: 1.file->settings->passwords 2.重启IDEA 3.执行一次提交或更新 当执行提交或更新之后,idea会自动提示输入账号.密 ...

  5. Deep Learning 和 Knowledge Graph howto

    领军大家: Geoffrey E. Hinton http://www.cs.toronto.edu/~hinton/ 阅读列表: reading lists and survey papers fo ...

  6. 使用require.js

    requirejs使用入门 什么是requirejs? RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤.可以用它来加速.优化代码,但其主要 ...

  7. DotNetty 跨平台的网络通信库(转)

    久以来,.Net开发人员都非常羡慕Java有Netty这样,高效,稳定又易用的网络通信基础框架.终于微软的Azure团队,使用C#实现的Netty的版本发布.不但使用了C#和.Net平台的技术特点,并 ...

  8. 解决jQuery在chrome中获取height为0

    笔者之前在一家创业公司做过项目,当时遇到这么一个奇怪的问题,我需要用一个jQuery的height()方法获取一个div的高度,但是在chrome浏览器上面有时可以正常获取,但是同一个页面刷新多几次获 ...

  9. 5.jQuery&Ajax

    1.jQuery 什么是 jQuery ? jQuery是一个JavaScript函数库.jQuery是一个轻量级的"写的少,做的多"的JavaScript库.包含以下功能: HT ...

  10. css中的伪元素,我今天记住了!o~yeah

    对于伪类和伪元素,我如果要区别它们,一般是使用css中的手册来区分,平常时候也没特意去记,需要用到时打开手册“哦,这个是伪元素,这个是伪类”,我个人觉的某些东西你把它存在网上,不一定要存在头脑中.带着 ...