【问题标题】:CUDA: working with arrays of different sizesCUDA:处理不同大小的数组
【发布时间】:2014-08-11 14:57:03
【问题描述】:

在此示例中,我尝试使用 10x9 数组中的值创建一个 10x8 数组。看起来我访问内存不正确,但我不确定我的错误在哪里。

C++ 中的代码类似于

for (int h = 0; h < height; h++){
    for (int i = 0; i < (width-2); i++)
        dd[h*(width-2)+i] = hi[h*(width-1)+i] + hi[h*(width-1)+i+1];
}

这就是我在 CUDA 中尝试的:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <stdint.h>

#include <iostream>

#define TILE_WIDTH 4

using namespace std;

__global__ void cudaOffsetArray(int height, int width, float *HI, float *DD){

    int             x                   =   blockIdx.x * blockDim.x + threadIdx.x; // Col // width
    int             y                   =   blockIdx.y * blockDim.y + threadIdx.y; // Row // height
    int             grid_width          =   gridDim.x  * blockDim.x;
  //int             index               =   y * grid_width + x;

    if ((x < (width - 2)) && (y < (height)))
        DD[y * (grid_width - 2) + x] = (HI[y * (grid_width - 1) + x] + HI[y * (grid_width - 1) + x + 1]);
}

int main(){

    int height  = 10;
    int width   = 10;

    float *HI = new float [height * (width - 1)];
    for (int i = 0; i < height; i++){
        for (int j = 0; j < (width - 1); j++)
            HI[i * (width - 1) + j] = 1;
    }

    float   *gpu_HI;
    float   *gpu_DD;
    cudaMalloc((void **)&gpu_HI, (height * (width - 1) * sizeof(float)));
    cudaMalloc((void **)&gpu_DD, (height * (width - 2) * sizeof(float)));

    cudaMemcpy(gpu_HI, HI, (height * (width - 1) * sizeof(float)), cudaMemcpyHostToDevice);

    dim3            dimGrid((width - 1) / TILE_WIDTH + 1, (height - 1)/TILE_WIDTH + 1, 1);
    dim3            dimBlock(TILE_WIDTH, TILE_WIDTH, 1);

    cudaOffsetArray<<<dimGrid,dimBlock>>>(height, width, gpu_HI, gpu_DD);

    float *result   = new float[height * (width - 2)];
    cudaMemcpy(result, gpu_DD,  (height * (width - 2) * sizeof(float)), cudaMemcpyDeviceToHost);

    for (int i = 0; i < height; i++){
        for (int j = 0; j < (width - 2); j++)
            cout << result[i * (width - 2) + j] << " ";
        cout << endl;
    }

    cudaFree(gpu_HI);
    cudaFree(gpu_DD);
    delete[] result;
    delete[] HI;

    system("pause");
}

我在全局函数中也试过这个:

if ((x < (width - 2)) && (y < (height)))
    DD[y * (grid_width - 2) + (blockIdx.x - 2) * blockDim.x + threadIdx.x] = 
        (HI[y * (grid_width - 1) + (blockIdx.x - 1) * blockDim.x + threadIdx.x] + 
         HI[y * (grid_width - 1) + (blockIdx.x - 1) * blockDim.x + threadIdx.x + 1]);

【问题讨论】:

  • 使用向量,当你越界时它会告诉你。
  • @NeilKirk 你的意思是使用推力库吗?我刚刚读到这些仅在主机端可用,您不能在设备功能中使用它们。这是错误的还是你能给我任何额外的信息?
  • 我不知道什么是 Cuda。我指的是 std::vector
  • std::vector 在 CUDA 设备代码中不方便使用。 thrust::device_vector 也不方便在 CUDA 设备代码中使用。

标签: c++ arrays memory cuda


【解决方案1】:

要“修复”您的代码,请将内核中此行中 grid_width 的每次使用更改为 width

    DD[y * (grid_width - 2) + x] = (HI[y * (grid_width - 1) + x] + HI[y * (grid_width - 1) + x + 1]);

像这样:

    DD[y * (width - 2) + x] = (HI[y * (width - 1) + x] + HI[y * (width - 1) + x + 1]);

解释:

你的grid_width

dim3            dimGrid((width * 2 - 1) / TILE_WIDTH + 1, (height - 1)/TILE_WIDTH + 1, 1);
dim3            dimBlock(TILE_WIDTH, TILE_WIDTH, 1);

实际上并不对应于您的数组大小(10x10、10x9 或 10x8)。我不确定你为什么要在 x 维度上启动 2*width 线程,但这意味着你的线程数组比你的数据数组大得多。

所以当你在内核中使用grid_width 时:

    DD[y * (grid_width - 2) + x] = (HI[y * (grid_width - 1) + x] + HI[y * (grid_width - 1) + x + 1]);

索引将是一个问题。我认为,如果您将上面 grid_width 的每个实例改为仅 width (对应于数据数组的实际宽度),您将获得更好的索引。通常启动“额外线程”不是问题,因为您的内核中有一个线程检查行:

if ((x < (width - 2)) && (y < (height)))

但是当您启动额外的线程时,它会使您的网格变大,因此您不能使用网格尺寸正确索引到您的数据数组中。

【讨论】:

  • 抱歉,(width * 2) 是复制粘贴错误。我编辑了帖子,但修复后我的代码仍然不正确。我认为如果没有 *2,我会在 x 中获得 3 个(4x4)图块,在 y 中获得 3 个(4x4)图块,这就是我想要的,因为代码中的数组将混合大小。此外,我使用 10x10 作为示例,实际数组会大得多。
  • 请重新阅读我的回答。我不建议更改 width*2 条目。只需将内核中的grid_width 更改为width,正如我所指出的(只需在使用它的一行内核代码中的3 个位置更改它,正如我在我的答案中发布的那样),您的代码将被“修复”。这就是我所做的,它似乎有效。 here 是一个完整的例子。
  • 抱歉,我误解了,它似乎确实适用于该更改。非常感谢!
  • 如果我理解正确,在示例中,grid_width = 12,这就是索引错误的原因。
  • 在您发布的原始代码中,以及我在pastebin link 中包含的内容,grid_width = 20。您可以通过在内核代码中添加printf 语句轻松验证这一点。但是是的,当grid_widthwidth 不同时,您对width 大小数据数组的索引将不正确。如果你在普通的 C 代码中这样做,它也不会正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
相关资源
最近更新 更多