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') ...
随机推荐
- 16Flutter中的路由 基本路由 基本路由跳转传值(上)
/* Flutter中的普通路由.普通路由传值.命名路由.命名路由传值 Flutter中的路由通俗的讲就是页面跳转.在Flutter中通过Navigator组件管理路由导航. 并提供了管理堆栈的方法. ...
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_23-页面预览-页面预览开发
1.用户进入cms前端,点击“页面预览”在浏览器请求cms页面预览链接. 2.cms根据页面id查询DataUrl并远程请求DataUrl获取数据模型. 3.cms根据页面id查询页面模板内容 4.c ...
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_03-freemarker测试环境搭建
新建一个module 选择parent test-freemarker spring‐boot‐starter‐freemarker:spring boot 提供的关于 freemaker的相关的包 ...
- 读写Session
读写Session Session是保存在服务端的字典 Session与Cookie有些类似,都是通过字典管理key-value对,只不过Cookie是保存在客户端的字典,而Session是保存在服务 ...
- 解决Unity3d 图片黑边问题
突然发现UI有黑边,在Photoshop里面没发现问题. 最后在图集的属性中去掉Minimap选项就可以了.
- 网页是如何实现从剪贴板从读取图片并上传到server的
代码比较简单,原理更简单,不多言请直接看代码. <!DOCTYPE html> <html> <head> <meta charset="UTF-8 ...
- Hyperledger Fabric 安全基础:身份系统 PKIs
什么是身份系统 区块链网络中的角色包括对等节点(peer),订购着,客户端应用程序,管理员等等.这些参与者的身份都封装在X.509数字证书中.这些身份信息真的非常重要,因为他们决定了在网络中参与者具体 ...
- spring的控制器如何获取参数
1.控制器代码 获取参数的注解 @RequestParam(name="name", required=false, defaultValue="World") ...
- 在C#中简单使用gRPC
一.引言 本文采用gRPC官方提供的一个教程例子,通过这个例子可以学习到在.proto文件中定义服务.使用protocol buffer编译器生成服务器和客户端代码.使用C#gRPC API为您的服务 ...
- 在vue项目中,将juery设置为全局变量
1.首先执行:npm install jQuery --save-dev,在package.json里加入jQuery. 2.修改build下的webpack.base.conf.js 方法一: 首 ...