向CUDA内核发送3d阵列
我将给出的代码作为答案,尝试将其用于3D而不是2D,并对其他部分进行了轻微更改,现在看起来如下所示:向CUDA内核发送3d阵列,c,cuda,gpu,gpgpu,C,Cuda,Gpu,Gpgpu,我将给出的代码作为答案,尝试将其用于3D而不是2D,并对其他部分进行了轻微更改,现在看起来如下所示: __global__ void doSmth(int*** a) { for(int i=0; i<2; i++) for(int j=0; j<2; j++) for(int k=0; k<2; k++) a[i][j][k]=i+j+k; } int main() { int*** h_c = (int***) malloc(2*s
__global__ void doSmth(int*** a) {
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
a[i][j][k]=i+j+k;
}
int main() {
int*** h_c = (int***) malloc(2*sizeof(int**));
for(int i=0; i<2; i++) {
h_c[i] = (int**) malloc(2*sizeof(int*));
for(int j=0; j<2; j++)
GPUerrchk(cudaMalloc((void**)&h_c[i][j],2*sizeof(int)));
}
int*** d_c;
GPUerrchk(cudaMalloc((void****)&d_c,2*sizeof(int**)));
GPUerrchk(cudaMemcpy(d_c,h_c,2*sizeof(int**),cudaMemcpyHostToDevice));
doSmth<<<1,1>>>(d_c);
GPUerrchk(cudaPeekAtLastError());
int res[2][2][2];
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
GPUerrchk(cudaMemcpy(&res[i][j][0],
h_c[i][j],2*sizeof(int),cudaMemcpyDeviceToHost));
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
printf("[%d][%d][%d]=%d\n",i,j,k,res[i][j][k]);
}
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuovoid doSmth(内部***a){
对于(int i=0;i首先,我认为Talonmes在发布对您提到的上一个问题的回复时,并不打算代表良好的编码。因此,弄清楚如何将其扩展到3D可能不是对您时间的最佳利用。例如,为什么我们要编写只使用一个线程的程序?而可能有be此类内核的合法使用,这不是其中之一。您的内核可以并行执行一系列独立工作,但您将所有工作强制到一个线程上,并将其序列化。并行工作的定义是:
a[i][j][k]=i+j+k;
让我们看看如何在GPU上并行处理
我要做的另一个介绍性观察是,由于我们正在处理的问题的大小是预先知道的,所以让我们使用C来处理这些问题,并尽可能从语言中获益。在某些情况下可能需要嵌套循环来执行Cudamaloc,但我认为这不是其中之一
下面是一个并行完成工作的代码:
#include <stdio.h>
#include <stdlib.h>
// set a 3D volume
// To compile it with nvcc execute: nvcc -O2 -o set3d set3d.cu
//define the data set size (cubic volume)
#define DATAXSIZE 100
#define DATAYSIZE 100
#define DATAZSIZE 20
//define the chunk sizes that each threadblock will work on
#define BLKXSIZE 32
#define BLKYSIZE 4
#define BLKZSIZE 4
// for cuda error checking
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
return 1; \
} \
} while (0)
// device function to set the 3D volume
__global__ void set(int a[][DATAYSIZE][DATAXSIZE])
{
unsigned idx = blockIdx.x*blockDim.x + threadIdx.x;
unsigned idy = blockIdx.y*blockDim.y + threadIdx.y;
unsigned idz = blockIdx.z*blockDim.z + threadIdx.z;
if ((idx < (DATAXSIZE)) && (idy < (DATAYSIZE)) && (idz < (DATAZSIZE))){
a[idz][idy][idx] = idz+idy+idx;
}
}
int main(int argc, char *argv[])
{
typedef int nRarray[DATAYSIZE][DATAXSIZE];
const dim3 blockSize(BLKXSIZE, BLKYSIZE, BLKZSIZE);
const dim3 gridSize(((DATAXSIZE+BLKXSIZE-1)/BLKXSIZE), ((DATAYSIZE+BLKYSIZE-1)/BLKYSIZE), ((DATAZSIZE+BLKZSIZE-1)/BLKZSIZE));
// overall data set sizes
const int nx = DATAXSIZE;
const int ny = DATAYSIZE;
const int nz = DATAZSIZE;
// pointers for data set storage via malloc
nRarray *c; // storage for result stored on host
nRarray *d_c; // storage for result computed on device
// allocate storage for data set
if ((c = (nRarray *)malloc((nx*ny*nz)*sizeof(int))) == 0) {fprintf(stderr,"malloc1 Fail \n"); return 1;}
// allocate GPU device buffers
cudaMalloc((void **) &d_c, (nx*ny*nz)*sizeof(int));
cudaCheckErrors("Failed to allocate device buffer");
// compute result
set<<<gridSize,blockSize>>>(d_c);
cudaCheckErrors("Kernel launch failure");
// copy output data back to host
cudaMemcpy(c, d_c, ((nx*ny*nz)*sizeof(int)), cudaMemcpyDeviceToHost);
cudaCheckErrors("CUDA memcpy failure");
// and check for accuracy
for (unsigned i=0; i<nz; i++)
for (unsigned j=0; j<ny; j++)
for (unsigned k=0; k<nx; k++)
if (c[i][j][k] != (i+j+k)) {
printf("Mismatch at x= %d, y= %d, z= %d Host= %d, Device = %d\n", i, j, k, (i+j+k), c[i][j][k]);
return 1;
}
printf("Results check!\n");
free(c);
cudaFree(d_c);
cudaCheckErrors("cudaFree fail");
return 0;
}
#包括
#包括
//设置三维体积
//要使用nvcc编译它,请执行:nvcc-O2-o set3d set3d.cu
//定义数据集大小(立方体积)
#定义DATAXSIZE 100
#定义DATAYSIZE 100
#定义DATAZSIZE 20
//定义每个threadblock将使用的块大小
#定义BLKXSIZE 32
#定义BLKYSIZE 4
#定义BLKZSIZE 4
//用于cuda错误检查
#定义cudaCheckErrors(msg)\
做{\
cudaError\u t\u err=cudaGetLastError()\
如果(_err!=cudaSuccess){\
fprintf(标准,“致命错误:%s(%s位于%s:%d)\n”\
msg,cudaGetErrorString(_err)\
__文件(行)\
fprintf(stderr,“***失败-中止\n”)\
返回1\
} \
}而(0)
//用于设置三维体积的设备功能
__全局无效集(int a[][DATAYSIZE][DATAXSIZE])
{
无符号idx=blockIdx.x*blockDim.x+threadIdx.x;
无符号idy=blockIdx.y*blockDim.y+threadIdx.y;
无符号idz=blockIdx.z*blockDim.z+threadIdx.z;
如果((idx<(DATAXSIZE))&&(idy<(DATAYSIZE))&&(idz<(DATAZSIZE))){
a[idz][idy][idx]=idz+idy+idx;
}
}
int main(int argc,char*argv[])
{
typedef int nraray[DATAYSIZE][DATAXSIZE];
常量dim3块大小(BLKXSIZE、BLKYSIZE、BLKZSIZE);
常量dim3网格大小((DATAXSIZE+BLKXSIZE-1)/BLKXSIZE),((DATAYSIZE+BLKYSIZE-1)/BLKYSIZE),((DATAZSIZE+BLKZSIZE-1)/BLKZSIZE));
//总体数据集大小
const int nx=DATAXSIZE;
const int ny=数据物理化;
const int nz=DATAZSIZE;
//通过malloc存储数据集的指针
nRarray*c;//存储在主机上的结果的存储
nRarray*d_c;//存储设备上计算的结果
//为数据集分配存储
如果((c=(nRarray*)malloc((nx*ny*nz)*sizeof(int))==0{fprintf(stderr,“malloc1 Fail\n”);返回1;}
//分配GPU设备缓冲区
Cudamaloc((void**)和d_c,(nx*ny*nz)*sizeof(int));
cudaCheckErrors(“未能分配设备缓冲区”);
//计算结果
set(d_c);
cudaCheckErrors(“内核启动失败”);
//将输出数据复制回主机
cudaMemcpy(c,d_c,((nx*ny*nz)*sizeof(int)),cudaMemcpyDeviceToHost);
CUDACHECKERS(“CUDA memcpy故障”);
//并检查其准确性
对于(unsigned i=0;ithanks,plz你能告诉我如何用我目前的方式解决这个问题吗?非常感谢!你能提供一个完整的、可编译的例子来说明你想做什么吗?这是为了方便那些试图帮助你的人。如果我问得不对,很抱歉。上面的例子是完整的。如果我愿意改变的话有任何东西,那就是“h_c”的大小,它可能变成“int****”其中每个子阵列都有非常大和不同的大小。谢谢!如果我问错了,再次表示歉意。事先非常感谢您的帮助。您提供的示例不完整或不可编译。一个原因是您没有在任何地方定义gpuerchk。是的,我可以转到上一个问题并拼凑出您的意图通过将该示例中的一些内容与您的结合起来,但这很不方便,特别是因为您可能拥有完整的代码并正在编译它。无论如何,我已经更新了我的答案,以向您展示如何以您当前的方式解决它。我知道这可能太多了,但是否可以只使用h_c而不使用h_c有h_c1的部分?谢谢!!!
#include <cstdio>
inline void GPUassert(cudaError_t code, char * file, int line, bool Abort=true)
{
if (code != 0) {
fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line);
if (Abort) exit(code);
}
}
#define GPUerrchk(ans) { GPUassert((ans), __FILE__, __LINE__); }
__global__ void doSmth(int*** a) {
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
a[i][j][k]=i+j+k;
}
int main() {
int*** h_c = (int***) malloc(2*sizeof(int**));
for(int i=0; i<2; i++) {
h_c[i] = (int**) malloc(2*sizeof(int*));
for(int j=0; j<2; j++)
GPUerrchk(cudaMalloc((void**)&h_c[i][j],2*sizeof(int)));
}
int ***h_c1 = (int ***) malloc(2*sizeof(int **));
for (int i=0; i<2; i++){
GPUerrchk(cudaMalloc((void***)&(h_c1[i]), 2*sizeof(int*)));
GPUerrchk(cudaMemcpy(h_c1[i], h_c[i], 2*sizeof(int*), cudaMemcpyHostToDevice));
}
int*** d_c;
GPUerrchk(cudaMalloc((void****)&d_c,2*sizeof(int**)));
GPUerrchk(cudaMemcpy(d_c,h_c1,2*sizeof(int**),cudaMemcpyHostToDevice));
doSmth<<<1,1>>>(d_c);
GPUerrchk(cudaPeekAtLastError());
int res[2][2][2];
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
GPUerrchk(cudaMemcpy(&res[i][j][0], h_c[i][j],2*sizeof(int),cudaMemcpyDeviceToHost));
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
printf("[%d][%d][%d]=%d\n",i,j,k,res[i][j][k]);
}