今天想起一个问题,看到的绝大多数CUDA代码都是使用的一维数组,是否可以在CUDA中使用一维数组,这是一个问题,想了各种问题,各种被77的错误状态码和段错误折磨,最后发现有一个cudaMallocManaged函数,这个函数可以很好的组织多维数组的多重指针的形式

,后来发现,这个问题之前在Stack Overflow中就有很好的解决。先贴一下我自己的代码实现:

 #include "cuda_runtime.h"
#include "device_launch_parameters.h" #include <stdio.h>
const int arraySize = ;
cudaError_t addWithCuda(int *c, const int *a, const int *b, size_t size); __global__ void addKernel(int **c, const int *a, const int *b)
{
int i = threadIdx.x;
if(i<arraySize)
c[][i] = a[i] + b[i];
else
c[][i-arraySize]= a[i-arraySize]+b[i-arraySize];
} int main()
{ const int a[arraySize] = { , , , , };
const int b[arraySize] = { , , , , };
int c[arraySize] = { }; // Add vectors in parallel.
cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addWithCuda failed!");
return ;
} printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
c[], c[], c[], c[], c[]); // cudaThreadExit must be called before exiting in order for profiling and
// tracing tools such as Nsight and Visual Profiler to show complete traces.
cudaStatus = cudaThreadExit();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaThreadExit failed!");
return ;
} return ;
} // Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(int *c, const int *a, const int *b, size_t size)
{
int *dev_a = ;
int *dev_b = ;
int *dev_c0;
int **dev_c ;
cudaError_t cudaStatus; // Choose which GPU to run on, change this on a multi-GPU system.
cudaStatus = cudaSetDevice();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
goto Error;
} // Allocate GPU buffers for three vectors (two input, one output)
cudaStatus = cudaMallocManaged(&dev_c, *sizeof(int*));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
}
cudaStatus = cudaMalloc((void**)&(dev_c0), size * sizeof(int)*);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} dev_c[]=dev_c0;
dev_c[]=dev_c0+arraySize;
cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} // Copy input vectors from host memory to GPU buffers.
cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} // Launch a kernel on the GPU with one thread for each element.
addKernel<<<, size*>>>(dev_c, dev_a, dev_b); // cudaThreadSynchronize waits for the kernel to finish, and returns
// any errors encountered during the launch.
cudaStatus = cudaThreadSynchronize();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaThreadSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
goto Error;
} // Copy output vector from GPU buffer to host memory.
cudaStatus = cudaMemcpy(c, dev_c[], size * sizeof(int), cudaMemcpyDeviceToHost);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} Error: cudaFree(dev_a);
cudaFree(dev_b); return cudaStatus;
}

在别人很好的代码下就不漏丑了,贴一下stack overflow的代码,非常直观易懂

 //https://stackoverflow.com/questions/40388242/multidimensional-array-allocation-with-cuda-unified-memory-on-power-8

 #include <iostream>
#include <assert.h> template<typename T>
T**** create_4d_flat(int a, int b, int c, int d) {
T *base;
cudaError_t err = cudaMallocManaged(&base, a*b*c*d * sizeof(T));
assert(err == cudaSuccess);
T ****ary;
err = cudaMallocManaged(&ary, (a + a * b + a * b*c) * sizeof(T*));
assert(err == cudaSuccess);
for (int i = ; i < a; i++) {
ary[i] = (T ***)((ary + a) + i * b);
for (int j = ; j < b; j++) {
ary[i][j] = (T **)((ary + a + a * b) + i * b*c + j * c);
for (int k = ; k < c; k++)
ary[i][j][k] = base + ((i*b + j)*c + k)*d;
}
}
return ary;
} template<typename T>
void free_4d_flat(T**** ary) {
if (ary[][][]) cudaFree(ary[][][]);
if (ary) cudaFree(ary);
} template<typename T>
__global__ void fill(T**** data, int a, int b, int c, int d) {
unsigned long long int val = ;
for (int i = ; i < a; i++)
for (int j = ; j < b; j++)
for (int k = ; k < c; k++)
for (int l = ; l < d; l++)
data[i][j][k][l] = val++;
} void report_gpu_mem()
{
size_t free, total;
cudaMemGetInfo(&free, &total);
std::cout << "Free = " << free << " Total = " << total << std::endl;
} int main() {
report_gpu_mem(); unsigned long long int ****data2;
std::cout << "allocating..." << std::endl;
data2 = create_4d_flat<unsigned long long int>(, , , ); report_gpu_mem(); fill << <, >> > (data2, , , , );
cudaError_t err = cudaDeviceSynchronize();
assert(err == cudaSuccess); std::cout << "validating..." << std::endl;
for (int i = ; i < * * * ; i++)
if (*(data2[][][] + i) != i) { std::cout << "mismatch at " << i << " was " << *(data2[][][] + i) << std::endl; return -; }
free_4d_flat(data2);
return ;
}

CUDA中使用多维数组的更多相关文章

  1. C#中读取二维数组每位的长度

    C#中的二维数组,如int[,] A=new int[a,b];则 a=A.GetLength(0);即可获得二维数组中第一维的长度. b=A.GetLength(1);即可获得二维数组中第二维的长度 ...

  2. Java中的二维数组

    Java 中的二维数组 所谓二维数组,可以简单的理解为是一种"特殊"的一维数组,它的每个数组空间中保存的是一个一维数组. 那么如何使用二维数组呢,步骤如下: 1. 声明数组并分配空 ...

  3. Py中的多维数组ndarray学习【转载】

    转自:http://blog.sciencenet.cn/home.php?mod=space&uid=3031432&do=blog&id=1064033 1. NumPy中 ...

  4. iOS中的二维数组

    首先我们知道OC中是没有二维数组的,二维数组是通过一位数组的嵌套实现的,但是别忘了我们有字面量,实际上可以和C/C++类似的简洁地创建和使用二维数组.这里总结了创建二维数组的两种方法以及数组的访问方式 ...

  5. 一些Python中的二维数组的操作方法

    一些Python中的二维数组的操作方法 这篇文章主要介绍了一些Python中的二维数组的操作方法,是Python学习当中的基础知识,需要的朋友可以参考下 需要在程序中使用二维数组,网上找到一种这样的用 ...

  6. 如何在C中传递二维数组作为参数?

    回答: 在C语言中,有很多方法可以将2d数组作为参数传递.在下面的部分中,我描述了将2d数组作为参数传递给函数的几种方法. 使用指针传递2d数组以在c中运行 多维数组的第一个元素是另一个数组,所以在这 ...

  7. php中遍历二维数组并以表格的形式输出

    一.索引数组 <?php //使用array()语句结构将联系人列表中所有数据声明为一个二维数组,默认下标是顺序数字索引 $contact1 = array( //定义外层数组 array(1, ...

  8. Java 中的二维数组

    所谓二维数组,可以简单的理解为是一种“特殊”的一维数组,它的每个数组空间中保存的是一个一维数组. 那么如何使用二维数组呢,步骤如下: 1. 声明数组并分配空间 或者 如: 2. 赋值 二维数组的赋值, ...

  9. python中的二维数组90度旋转

    data=[[col for col in range(4)] for raw in range(4)] #创建一个二维数组 for n in data: print (n) print('\n') ...

随机推荐

  1. kotlin之MutableMap委托

    fun main(arg: Array<String>) { val map = mutableMapOf("name" to "tom", ) v ...

  2. JAVA 基础编程练习题42 【程序 42 求数字】

    42 [程序 42 求数字] 题目:809*??=800*??+9*??+1 其中??代表的两位数,8*??的结果为两位数,9*??的结果为 3 位数.求??代表的两位数,及 809*??后的结 果. ...

  3. Flutter的布局方法

    重点是什么? Widgets 是用于构建UI的类. Widgets 用于布局和UI元素. 通过简单的widget来构建复杂的widget Flutter布局机制的核心就是widget.在Flutter ...

  4. django 之(五) --- 验证码|富文本|邮箱短信

    验证码 在用户登录,注册以及一些敏感操作的时候,我们为了防止服务器被暴力请求,或爬虫爬取,我们可以使用验证码进行过滤,减轻服务器的压力. 原生实现: 库名:pip install Pillow     ...

  5. 阿里云Centos 7.6安装Redis以及开启远程连接

    下载地址:http://redis.io/download,下载最新稳定版本. 本教程使用的最新文档版本为 5.0.5,下载并安装: $ wget http://download.redis.io/r ...

  6. 彻底搞定Javascript事件循环

    参考链接:https://juejin.im/post/5dca8a8be51d45227239abc4?utm_medium=hao.caibaojian.com&utm_source=ha ...

  7. sort(()=>{return Math.random()-0.5)}乱序数组不准确

    为什么sort(()=>{return Math.random()-0.5)}乱序数组不准确.(注意结合插入排序原理来理解) @1.chrome浏览器对于数组长度10以内为插入排序.反之则快速排 ...

  8. Linux回收站的路径在哪里?

    linux 回收站的路径:-/.local/share/Trash

  9. Hash冲突的四种解决办法

    一.哈希表简介 非哈希表的特点:关键字在表中的位置和它自检不存在一个确定的关系,查找的过程为给定值一次和各个关系自进行比较,查找的效率取决于给定值进行比较的次数. 哈希表的特点:关键字在表中位置和它自 ...

  10. Windows 与 linux文件相互传输的方法

    公司里面办公机器大部分都是 windows 但是现在随着云计算.docker.linux等的越来越兴起,需要大量的操作linux服务器. 最重要和最直接的需要将windows 上面的文件上传到 lin ...