现在的位置: 首页 > 综合 > 正文

在CUDA如何使用二维数组(**[M][N])

2013年08月14日 ⁄ 综合 ⁄ 共 2046字 ⁄ 字号 评论关闭

总有些童鞋想知道怎么在CUDA中使用二维数组([M][N]这种类型),其实这个很简单,不过你要完全弄明白,必须对指针,地址等概念非常清楚才行。写这篇博客解决下大家这个问题:

1、首先讲述一下在一般C语言中如何使用二维数组。

int r, c;
int **arr = (int**)malloc(ROWS*sizeof(int*));
int *data = (int*)malloc(COLS*ROWS*sizeof(int));
for (r = 0; r < ROWS; r++)
{
	arr[r] = data + r*COLS;
}

free(arr);
free(data);

    代码中的arr实个二维数组变量了,你可以在for循环之后arr[i][j]的方式使用它。

 

2、告诉你如何在CUDA中使用二维数组可以类比1中的方法,不过你要清楚几点,这几点在代码之后说明。

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

#define ROWS 32
#define COLS 16
#define CHECK(res) if(res!=cudaSuccess){exit(-1);}
__global__ void Kerneltest(int **da, unsigned int rows, unsigned int cols)
{
	unsigned int row = blockDim.y*blockIdx.y + threadIdx.y;
	unsigned int col = blockDim.x*blockIdx.x + threadIdx.x;
	if (row < rows && col < cols)
	{
		da[row][col] = row*cols + col;
	}
}

int main(int argc, char **argv)
{
	int **da = NULL;
	int **ha = NULL;
	int *dc = NULL;
	int *hc = NULL;
	cudaError_t res;
	int r, c;
	bool is_right=true;

	res = cudaMalloc((void**)(&da), ROWS*sizeof(int*));CHECK(res)
	res = cudaMalloc((void**)(&dc), ROWS*COLS*sizeof(int));CHECK(res)
	ha = (int**)malloc(ROWS*sizeof(int*));
	hc = (int*)malloc(ROWS*COLS*sizeof(int));

	for (r = 0; r < ROWS; r++)
	{
		ha[r] = dc + r*COLS;
	}
	res = cudaMemcpy((void*)(da), (void*)(ha), ROWS*sizeof(int*), cudaMemcpyHostToDevice);CHECK(res)
	dim3 dimBlock(16,16);
	dim3 dimGrid((COLS+dimBlock.x-1)/(dimBlock.x), (ROWS+dimBlock.y-1)/(dimBlock.y));
	Kerneltest<<<dimGrid, dimBlock>>>(da, ROWS, COLS);
	res = cudaMemcpy((void*)(hc), (void*)(dc), ROWS*COLS*sizeof(int), cudaMemcpyDeviceToHost);CHECK(res)

	for (r = 0; r < ROWS; r++)
	{
		for (c = 0; c < COLS; c++)
		{
			printf("%4d ", hc[r*COLS+c]);
			if (hc[r*COLS+c] != (r*COLS+c))
			{
				is_right = false;
			}
		}
		printf("\n");
	}
	printf("the result is %s!\n", is_right? "right":"false");
	cudaFree((void*)da);
	cudaFree((void*)dc);
	free(ha);
	free(hc);
	getchar();
	return 0;
}

在CUDA中使用二维数组的几点说明:

1)da是一个二维变量,一定更不可以在33行的时候把ha改成da!一定要记住显存和内存是相互独立的,主机端的程序不可以直接操作显存!必须通过CUDA 提供的API函数来操作!

2)注意在内存申请时强制类型转换(void**)(&),怎么把***的变量转成**了!!这主要是API借口决定的,最好自己显式转换格式,避免不必要的麻烦。

3)看见数据拷贝的函数了吗,类型、类型、还是类型。

4)别忘了释放内存和显存!看见没,还是类型。

5)很希望这篇博客能帮到大家,可是我真的不推荐大家在GPU上使用二维数组!真的!!为什么呢?终归是效率惹的祸!显存的访问总是慢的。二维访存,可是连续访问了两次啊。要是老这样做,不但执行效率低,而且写代码也慢。如果对内存的概念不熟悉,千万别趟这趟浑水。看懂这段代码,就当是学习一下或者理解下内存、显存与内存独立的概念和规则吧。

附上执行结果:

 

抱歉!评论已关闭.