CUDA中使用多维数组
今天想起一个问题,看到的绝大多数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中使用多维数组的更多相关文章
- C#中读取二维数组每位的长度
C#中的二维数组,如int[,] A=new int[a,b];则 a=A.GetLength(0);即可获得二维数组中第一维的长度. b=A.GetLength(1);即可获得二维数组中第二维的长度 ...
- Java中的二维数组
Java 中的二维数组 所谓二维数组,可以简单的理解为是一种"特殊"的一维数组,它的每个数组空间中保存的是一个一维数组. 那么如何使用二维数组呢,步骤如下: 1. 声明数组并分配空 ...
- Py中的多维数组ndarray学习【转载】
转自:http://blog.sciencenet.cn/home.php?mod=space&uid=3031432&do=blog&id=1064033 1. NumPy中 ...
- iOS中的二维数组
首先我们知道OC中是没有二维数组的,二维数组是通过一位数组的嵌套实现的,但是别忘了我们有字面量,实际上可以和C/C++类似的简洁地创建和使用二维数组.这里总结了创建二维数组的两种方法以及数组的访问方式 ...
- 一些Python中的二维数组的操作方法
一些Python中的二维数组的操作方法 这篇文章主要介绍了一些Python中的二维数组的操作方法,是Python学习当中的基础知识,需要的朋友可以参考下 需要在程序中使用二维数组,网上找到一种这样的用 ...
- 如何在C中传递二维数组作为参数?
回答: 在C语言中,有很多方法可以将2d数组作为参数传递.在下面的部分中,我描述了将2d数组作为参数传递给函数的几种方法. 使用指针传递2d数组以在c中运行 多维数组的第一个元素是另一个数组,所以在这 ...
- php中遍历二维数组并以表格的形式输出
一.索引数组 <?php //使用array()语句结构将联系人列表中所有数据声明为一个二维数组,默认下标是顺序数字索引 $contact1 = array( //定义外层数组 array(1, ...
- Java 中的二维数组
所谓二维数组,可以简单的理解为是一种“特殊”的一维数组,它的每个数组空间中保存的是一个一维数组. 那么如何使用二维数组呢,步骤如下: 1. 声明数组并分配空间 或者 如: 2. 赋值 二维数组的赋值, ...
- python中的二维数组90度旋转
data=[[col for col in range(4)] for raw in range(4)] #创建一个二维数组 for n in data: print (n) print('\n') ...
随机推荐
- 前端 - 轮询, 长轮训, websocket
轮询 概念 ajax 轮询的原理很简单,让浏览器间隔几秒就发送一次请求,询问服务器是否有新信息 代码 function showUnreadNews() { $(document).ready(fun ...
- GPS模块编程之NMEA0183协议
NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式.现在已经成为GPS导航设备统一的RTCM(Rad ...
- android Vitamio Live 实时视频 记录
Vitamio 下载地址: https://github.com/yixia/VitamioBundle/releases https://github.com/yixia/VitamioBundle ...
- 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_15-异常处理-异常处理流程
右侧是框架报的异常 不可预知的,例如数据库连不上这一类的.可以在map中制定某些类的异常,如果找不到就最右边的 99999的, 系统对异常的处理使用统一的异常处理流程: 1.自定义异常类型. 2.自定 ...
- Eclipse安装Spring Tools Suites
第一种:离线安装 下载地址:较高版本 http://spring.io/tools/sts/all/ 比较低版本:http://spring.io/tools/ggts/all 选择适合自己Eclip ...
- 最新 咪咕java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.咪咕等10家互联网公司的校招Offer,因为某些自身原因最终选择了咪咕.6.7月主要是做系统复习.项目复盘.LeetCode ...
- 在VMware上安装centos
Windows,VMware和Centos三者的关系 VMware安装.centos安装 在 VMware 上安装 CentOS 第 1 步:打开 VMware,点击创建新的虚拟机 第 2 步:选择典 ...
- Web应用搭建
Web应用搭建 *资料库 http://www.oschina.net/project/tag/308/server-suite * web环境 http://www.freebuf.com/tool ...
- Hadoop学习(4)-mapreduce的一些注意事项
关于mapreduce的一些注意细节 如果把mapreduce程序打包放到了liux下去运行, 命令java –cp xxx.jar 主类名 如果报错了,说明是缺少相关的依赖jar包 用命令had ...
- Scala当中parallelize并行化的用法
[学习笔记] parallelize并行化集合是根据一个已经存在的Scala集合创建的RDD对象.集合的里面的元素将会被拷贝进入新创建出的一个可被并行操作的分布式数据集.例如:val rdd03 = ...