前言

  本文的目的很明确:介绍如何将二维数组传递进显存,以及如何将二维数组从显存传递回主机端。

实现步骤

  1. 在显存中为二维数组开辟空间

  2. 获取该二维数组在显存中的 pitch 值 (cudaMallocPitch 实现)

  3. 将二维数组传递进显存 (cudaMemcpy2D 实现)

  4. 在显存中对该二维数组进行处理 (目前必须按照 1 维数组的规则进行处理)

  5. 将结果传递回内存 (cudaMemcpy2D实现)

重要概念 - pitch

  对于内存的存取来说,对准偏移量为2的幂(现在一般要求2^4=16)的地址能获取更快的速度,而如果不对齐,可能你需要的数据需要更多的存取次数才能得到。

  为了满足这个条件,对于一个二维数组来说(行优先row major),就希望每一行的开头都满足“对齐”。如果一行的长度不规整,导致下一行开头不在指定的位置,就需要在每一行末尾进行填充(padding),从而使得每一行都对齐,这和BMP格式的像素存储是一个道理。

  pitch就是指每一行的字节数 + padding的字节数 。

  使用 cudaMemcpy2D 的目的仅是为了利用 pitch 机制提升二维数组中元素的访问速度。事实上二维数组传递进显存后,还是得按照一维数组的规范去处理该二维矩阵。global 函数中目前不支持多下标访问,好坑。。

代码示例

 #include "cuda.h"
#include "cuda_runtime.h" #include <iostream> using namespace std; // 定义测试二维数组的行列数
const int R = ;
const int C = ; int main()
{
// 定义一个用于测试的二维数组,其每个元素都赋值为0,并将其打印出来。
int array2D[R][C];
cout << "传输前的测试矩阵:" << endl;
for (int i=; i<R; i++) {
for (int j=; j<C; j++) {
array2D[i][j] = ;
cout << array2D[i][j] << " ";
}
cout << endl;
} // 再定义另一个同样大小的二维数组用于获取从显存传回的结果
int result[R][C];
cout << "传输前的结果矩阵:" << endl;
for (int i=; i<R; i++) {
for (int j=; j<C; j++) {
result[i][j] = ;
cout << result[i][j] << " ";
}
cout << endl;
} // 为此二维数组在显存中分配内存
int *d_array2D;
cudaMalloc ((void**)&d_array2D, sizeof(int)*R*C); // 获取显存中的二维数组的 pitch 值
size_t d_pitch;
cudaMallocPitch ((void**) &d_array2D, &d_pitch, sizeof(int)*C, R); // 将二维数组转移进显存
cudaMemcpy2D (
d_array2D, // 目的地址
d_pitch, // 目的 pitch
array2D, // 源地址
sizeof(int)*C, // 源 pitch
sizeof(int)*C, // 数据拷贝宽度
R, // 数据拷贝高度
cudaMemcpyHostToDevice // 数据传递方向
); // 将二维数组从显存传输回主机端的结果矩阵中
cudaMemcpy2D (
result, // 目的地址
sizeof(int)*C, // 目的 pitch
d_array2D, // 源地址
d_pitch, // 源 pitch
sizeof(int)*C, // 数据拷贝宽度
R, // 数据拷贝高度
cudaMemcpyDeviceToHost // 数据传递方向
); // 打印传回到结果矩阵的数据
cout << "从显存获取到测试矩阵后的结果矩阵:" << endl;
for (int i=; i<R; i++) {
for (int j=; j<C; j++) {
cout << result[i][j] << " ";
}
cout << endl;
} cudaFree (d_array2D); cin.get(); return EXIT_SUCCESS;
}

运行测试

  

小结

  本文介绍的仅仅是二维数组在两端之间的传输!当二维数组传递进了显存,在对其操作的过程中,是需要对其进行一个一维到二维的下标操作转换的,global 中不支持多下标访问。之所以加入 pitch 并使用 cudaMemcpy2D 只是为了提高元素的访问速度。

  如果需要具体处理传递进入的二维数组,还要将 pitch 也作为参数传递进 kernel 函数,如下所示:

// 下面的 kernel 函数将二维数组的所有位置为 2
__global__
void kernelFun (int *d_array2D, int pitch)
{
for (int i=; i<R; i++) {
int *row = (int *)((char *)d_array2D+i*pitch);
for (int j=; j<C; j++) {
row[j] = ;
}
} return;
}

二维数组的传输 (host <-> device)的更多相关文章

  1. 第六篇:二维数组的传输 (host <-> device)

    前言 本文的目的很明确:介绍如何将二维数组传递进显存,以及如何将二维数组从显存传递回主机端. 实现步骤 1. 在显存中为二维数组开辟空间 2. 获取该二维数组在显存中的 pitch 值 (cudaMa ...

  2. 二维数组 cudaMallocPitch() 和三维数组 cudaMalloc3D() 的使用

    ▶ 使用函数 cudaMallocPitch() 和配套的函数 cudaMemcpy2D() 来使用二维数组.C 中二维数组内存分配是转化为一维数组,连贯紧凑,每次访问数组中的元素都必须从数组首元素开 ...

  3. dbda封装类(包括:返回二维数组、Ajax调用返回字符串、Ajax调用返回JSON)

    <?php class DBDA { public $host = "localhost"; public $uid = "root"; public $ ...

  4. MVC5中使用jQuery Post 二维数组和一维数组到Action

    很久没有写了,最近在做一个MVC项目,这是我做的第一个MVC项目.之前可以说多MVC一点都不了解,今天把昨天遇到的一个问题记录下来.MVC大神就请飘过吧,跟我遇到同样问题的可以进来看看.遇到的第一个问 ...

  5. PHP 二维数组根据某个字段排序

    二维数组根据某个字段排序有两种办法,一种是通过sort自己写代码,一种是直接用array_multisort排序函数 一. 手写arraysort PHP的一维数组排序函数: sort  对数组的值按 ...

  6. 剑指Offer-【面试题03:二维数组中的查找】

    package com.cxz.question3; /* * 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. * 请完成一个函数,输入这样的一个二维数组和 ...

  7. PHP开发笔记:二维数组根据某一项来进行排序

    比如说我们现在有一个二维数组: $arr = array( ‘d' => array(‘id' => 5, ‘name' => 1, ‘age' => 7), ‘b' => ...

  8. 剑指Offer面试题:2.二维数组中的查找

    一.题目:二维数组中的查找 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...

  9. PHP 根据key 给二维数组分组

    我们经常拿到一个二维数组出来,会发现结果和自己想要的有些偏差,可能需要根据二维数组里的某个字段对数组分组.先来看以下数组, Array ( [0] => Array ( [id] => 1 ...

随机推荐

  1. visio画UML用例图没有include关系的解决方法

    今天用Microsoft Visio画用例图时,发现visio UML用例里面找不到include关系,即“箭头”+“<>” 这个组件,后来终于发现一个可行的解决办法: 首先:打开Micr ...

  2. 使用ContentProvider管理多媒体-----查看多媒体数据中的所有图片

    import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; impo ...

  3. HDU 4089 Activation 概率DP 难度:3

    http://acm.hdu.edu.cn/showproblem.php?pid=4089 这道题中一共有两个循环: 1.事件1 如果一直落在Activation failed事件上,那么就会重新继 ...

  4. BindingNavigator操作DatagridView的数据

    参考 http://wenku.baidu.com/link?url=NWfEfArPZvDO_aI-xEKBHVGoZY9wQO_Oty_GCsGLiPspheCzFYLf_dytuWAqN2_0A ...

  5. python登陆,注册小程序

    def login(username,password): ''' 用于用户登录 :param username: 用户输入用户名 :param password: 用户输入密码 :return: T ...

  6. JavaScript去除数组中的重复性

    Array.prototype.unique = function () { var res = [], hash = {}; for (var i = 0, elem; (elem = this[i ...

  7. 3.5缺少动态连接库.so--cannot open shared object file: No such file or directory

    总结下来主要有3种方法:1. 用ln将需要的so文件链接到/usr/lib或者/lib这两个默认的目录下边 ln -s /where/you/install/lib/*.so /usr/lib sud ...

  8. [USACO精选] 第二章 动态规划(一)

    #4 公司利润 2014-01-16 这真的是动归?怎么觉得有点贪心的心态在.时间复杂度O(N),空间复杂度O(1),轻松加愉快!唯一要注意的是ANS一开始要赋负值,因为最终答案可能是负的. ; va ...

  9. PowerShell并发控制-命令行参数之四问

    传教士问: win下如何 获取进程命令行,及命令行参数? 传教士答: 可以用这个powershell命令(实际上是wmi查询): (get-wmiobject -query "select ...

  10. 在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案

    转自:http://www.jianshu.com/p/89687f618837 原因分析   当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误 ...