gpt4 book ai didi

loops - 如何使用嵌套 for 循环将两个二维(倾斜)数组相加?

转载 作者:行者123 更新时间:2023-11-30 17:36:17 25 4
gpt4 key购买 nike

假设,我想将两个二维数组添加到第三个二维数组中。

我正在使用以下代码:

cudaMallocPitch((void**)&device_a, &pitch, 2*sizeof(int),2);
cudaMallocPitch((void**)&device_b, &pitch, 2*sizeof(int),2);
cudaMallocPitch((void**)&device_c, &pitch, 2*sizeof(int),2);

请注意,我不想将这些数组用作展平的一维数组。我想使用两个 for 循环并将结果放入第三个数组中,如下所示:

__global__ void add(int *dev_a ,int *dev_b,int* dec_c)
{
for i=0;i<2;i++)
{
for j=0;j<2;j++)
{
dev_c[i][j]=dev_a[i][j]+dev_b[i][j];
}
}
}

如何在 CUDA 中执行此操作?

使用二维数组的内核调用应该是什么样的?

如果可能,请使用代码示例进行解释。

最佳答案

简短的回答是,你不能。 cudaMallocPitch()函数的作用正如其名称所暗示的那样,它分配倾斜线性内存,其中选择的倾斜对于 GPU 内存 Controller 和纹理硬件来说是最佳的。

如果您想在内核中使用指针数组,内核代码必须如下所示:

__global___ void add(int *dev_a[] ,int *dev_b[], int* dec_c[])
{
for i=0;i<2;i++) {
for j=0;j<2;j++) {
dev_c[i][j]=dev_a[i][j]+dev_b[i][j];
}
}
}

然后您需要在主机端嵌套 cudaMalloc 调用来构造指针数组并将其复制到设备内存。对于相当简单的 2x2 示例,分配单个数组的代码如下所示:

int ** h_a = (int **)malloc(2 * sizeof(int *));
cudaMalloc((void**)&h_a[0], 2*sizeof(int));
cudaMalloc((void**)&h_a[1], 2*sizeof(int));

int **d_a;
cudaMalloc((void ***)&d_a, 2 * sizeof(int *));
cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice);

这会将分配的设备指针数组保留在 d_a 中,然后您将其传递给内核。

出于代码复杂性和性能原因,您确实不想这样做,因为在 CUDA 代码中使用指针数组比使用线性内存的替代方案更难而且更慢。

<小时/>

为了展示 CUDA 中使用指针数组的愚蠢之处,这里是示例问题的完整工作示例,它结合了上面的两个想法:

#include <cstdio>
__global__ void add(int * dev_a[], int * dev_b[], int * dev_c[])
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
dev_c[i][j]=dev_a[i][j]+dev_b[i][j];
}
}
}

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__); }

int main(void)
{
const int aa[2][2]={{1,2},{3,4}};
const int bb[2][2]={{5,6},{7,8}};
int cc[2][2];

int ** h_a = (int **)malloc(2 * sizeof(int *));
for(int i=0; i<2;i++){
GPUerrchk(cudaMalloc((void**)&h_a[i], 2*sizeof(int)));
GPUerrchk(cudaMemcpy(h_a[i], &aa[i][0], 2*sizeof(int), cudaMemcpyHostToDevice));
}

int **d_a;
GPUerrchk(cudaMalloc((void ***)&d_a, 2 * sizeof(int *)));
GPUerrchk(cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice));

int ** h_b = (int **)malloc(2 * sizeof(int *));
for(int i=0; i<2;i++){
GPUerrchk(cudaMalloc((void**)&h_b[i], 2*sizeof(int)));
GPUerrchk(cudaMemcpy(h_b[i], &bb[i][0], 2*sizeof(int), cudaMemcpyHostToDevice));
}

int ** d_b;
GPUerrchk(cudaMalloc((void ***)&d_b, 2 * sizeof(int *)));
GPUerrchk(cudaMemcpy(d_b, h_b, 2*sizeof(int *), cudaMemcpyHostToDevice));

int ** h_c = (int **)malloc(2 * sizeof(int *));
for(int i=0; i<2;i++){
GPUerrchk(cudaMalloc((void**)&h_c[i], 2*sizeof(int)));
}

int ** d_c;
GPUerrchk(cudaMalloc((void ***)&d_c, 2 * sizeof(int *)));
GPUerrchk(cudaMemcpy(d_c, h_c, 2*sizeof(int *), cudaMemcpyHostToDevice));

add<<<1,1>>>(d_a,d_b,d_c);
GPUerrchk(cudaPeekAtLastError());

for(int i=0; i<2;i++){
GPUerrchk(cudaMemcpy(&cc[i][0], h_c[i], 2*sizeof(int), cudaMemcpyDeviceToHost));
}

for(int i=0;i<2;i++) {
for(int j=0;j<2;j++) {
printf("(%d,%d):%d\n",i,j,cc[i][j]);
}
}

return cudaThreadExit();
}

我建议您研究它,直到您了解它的作用,以及为什么与使用线性内存相比,它是一个糟糕的主意。

关于loops - 如何使用嵌套 for 循环将两个二维(倾斜)数组相加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22735949/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com