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是引用类型,直接将数组赋值给一个变量名,二者所指向的地址是一样的. 所以直接复制数组会产生意想不到的结构. 要想解决拷贝一个数组但是对副本的修改不影响原来的数组,有以下方式: ...
随机推荐
- g++ -I(大写i) 与-L(大写l)-l(小写l) 的作用与学习
linux 下 g++编译程序时,-I(大写i) 与-L(大写l)-l(小写l) 的作用 作为一个linux入门级使用者,gcc/g++ 的简单操作已经用过多次, 但是有时稍微复杂一点的程序就会使用到 ...
- python函数基础学习
函数的定义与调用: def 函数名(参数1,参数2): ‘’’函数注释’’’ print(‘函数体’) return 返回值 定 义:def关键字开关,空格之后接函数名和圆括号,最后冒号结尾 def ...
- Broken Keyboard (a.k.a. Beiju Text) UVA - 11988 (链表)
题目链接:https://vjudge.net/problem/UVA-11988 题目大意:输入一个字符串,输出在原本应该是怎么样的? 具体方法是 碰到' [ ' 回到最前面 碰到‘ ]’ 回 ...
- 性能测试工具LoadRunner01-性能测试基础
什么是性能测试? 在一定的约束条件下(指定的软件.硬件.网络环境等)对产品按一定的性能指标进行测试,确定系统能承受的最大负载压力,解决性能瓶颈.给用户最好的体验. 性能测试流程? 什么时候开始性能测试 ...
- (转)AIX下修改用户最大进程数
AIX下修改用户最大进程数 原文:http://blog.csdn.net/feichideche/article/details/39498555 使用AIX时候,切换用户,发现进程一直挂起,查看用 ...
- DEDE列表页和内容页调用顶级栏目ID的方法
dede模板中添加顶级栏目id的方法总结,使用dede顶级栏目id可以实现很多功能.比如,在每个列表页调用不同的栏目图片(同一顶级栏目调用相同的图片),如果我们做N个栏目就意味着要做N个列表页模板,显 ...
- springboot 整合redisson
整合代码已经过测试 1.pom <!-- redisson --> <dependency> <groupId>org.redisson</groupId&g ...
- css3重点回顾字体
1.字体 免费字体下载https://cn.ffonts.net/
- 菜鸟 学注册机编写之 Android app
0x00前言 环境及工具: 手机 Nexus 4(己root) 系统版本 Android 5.01 工具 AndroidKiller_V1.2 关于Android平台app注册机的编 ...
- BarCode条形码生成库
一.Barcode生成条形码的类库 二.示例 新建mvc空项目,添加Nuget引用 主要代码 // // GET: /Home/ public FileContentResult Index() { ...