cuda数组的拷贝
简单描述一下自己要做的事情:(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数组的拷贝的更多相关文章
- PHP 数组的拷贝是按值传递 or 按引用传递
在记忆中 PHP 简单变量的拷贝是按值传递,数组和对象的拷贝是按引用传递,即通过引用来实现. 简单变量和对象好理解: <?php // 简单变量的拷贝 $a = 'human'; $b = $a ...
- CUDA零内存拷贝 疑问考证
今天思考了一下CUDA零内存拷贝的问题,感觉在即将设计的程序中会派上用场,于是就查了一下相关信息. 以下是一些有帮助的链接: cuda中的零拷贝用法--针对二维指针 cuda中的零拷贝用法--针对一维 ...
- java-IO流-字符流-FileReader、FileWriter、自定义小数组的拷贝、BufferedReader、BufferedWriter、readLine()和newLine()方法、LineNumberReader、使用指定的码表读写字符
###21.01_IO流(字符流FileReader) * 1.字符流是什么 * 字符流是可以直接读写字符的IO流 * 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要 ...
- javascript数组操作(创建、元素删除、数组的拷贝)
这篇文章主要介绍了javascript数组操作,包括创建.元素的访问.元素删除.数组的拷贝等操作,还有其它示例,需要的朋友可以参考下 1.数组的创建 复制代码 代码如下: var arrayObj = ...
- 【CUDA开发】CUDA面内存拷贝用法总结
[CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...
- JS中数组的拷贝方法
之前在写一个vue的计算属性时,大概是这样: computed: { updateList () { let newList = this.List /*do something*/ return n ...
- java数组的拷贝和扩容
1.拷贝arraycopy方法 // 拷贝:arraycopy方法 // arraycopy // 第一个参数:原数组 // 第二个参数:原数组元素的起始位置 // 第三个参数:目标数组 // 第四个 ...
- Java一维与二维数组的拷贝与排序
Java一维与二维数组的拷贝与排序 目录 Java一维与二维数组的拷贝与排序 Arrays.sort() 一维数组升序排序 二维数组按行升序排序 二维数组按列升序排序 Java中的数组 Java中数组 ...
- js 数组的拷贝
在js中,数组Array是引用类型,直接将数组赋值给一个变量名,二者所指向的地址是一样的. 所以直接复制数组会产生意想不到的结构. 要想解决拷贝一个数组但是对副本的修改不影响原来的数组,有以下方式: ...
随机推荐
- python安装包的时候报错
python安装包的时候报错 今天兴致勃勃的安装了一个paramiko包,过程很顺利,但是到结尾的时候报错,这就让人不爽了. 所以呢,需要安装一个名为python-dev的软件包. 该软件包包括头文件 ...
- oracle 用mybatis生成主键
oracle主键是不能像mysql一样自动管理的,需要自己手动管理,先生成,再插入. <selectKey keyProperty="id" resultType=" ...
- 工作中常用到的sql命令!!!
一.mysql数据库日常操作. 1.启动mysql:/etc/init.d/mysql start (前面为mysql的安装路径) 2.重启mysql: /etc/init.d/my ...
- IDEA修改git账号及密码的方法
IDEA修改git账号及密码的方法: 1.file->settings->passwords 2.重启IDEA 3.执行一次提交或更新 当执行提交或更新之后,idea会自动提示输入账号.密 ...
- Deep Learning 和 Knowledge Graph howto
领军大家: Geoffrey E. Hinton http://www.cs.toronto.edu/~hinton/ 阅读列表: reading lists and survey papers fo ...
- 使用require.js
requirejs使用入门 什么是requirejs? RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤.可以用它来加速.优化代码,但其主要 ...
- DotNetty 跨平台的网络通信库(转)
久以来,.Net开发人员都非常羡慕Java有Netty这样,高效,稳定又易用的网络通信基础框架.终于微软的Azure团队,使用C#实现的Netty的版本发布.不但使用了C#和.Net平台的技术特点,并 ...
- 解决jQuery在chrome中获取height为0
笔者之前在一家创业公司做过项目,当时遇到这么一个奇怪的问题,我需要用一个jQuery的height()方法获取一个div的高度,但是在chrome浏览器上面有时可以正常获取,但是同一个页面刷新多几次获 ...
- 5.jQuery&Ajax
1.jQuery 什么是 jQuery ? jQuery是一个JavaScript函数库.jQuery是一个轻量级的"写的少,做的多"的JavaScript库.包含以下功能: HT ...
- css中的伪元素,我今天记住了!o~yeah
对于伪类和伪元素,我如果要区别它们,一般是使用css中的手册来区分,平常时候也没特意去记,需要用到时打开手册“哦,这个是伪元素,这个是伪类”,我个人觉的某些东西你把它存在网上,不一定要存在头脑中.带着 ...