c - 你如何在cuda中创建一个二维数组

标签 c cuda

为了练习,我正在用 cuda 编写一个简单的矩阵初始化程序。作为起点,我制作了一个小的顺序版本以供引用。它只是创建一个 n x m 数组并用 double 填充它。我一直在阅读其他帖子和文档,但我很困惑,我希望有人能向我解释如何在 cuda 中以类似于我在下面所做的 n x m 大小的方式初始化二维数组。如果有人愿意解释,我也很感激关于如何填充该 cuda 矩阵的见解。

您好,关于它是否可能重复,我应该详细说明。链接的帖子并没有真正解释任何东西,它只是示例代码,它是我之前查看过但不理解的帖子之一,因为它没有解释。谢谢。

顺序版本:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

int n,m, i, j;
double count;

void update(int n, int m, double arr[][m]){
  for(i=0; i<n; i++){
    for(j=0; j<m; j++){
      count++;
      arr[i][j] = count;
    }
  }
}


int main(int argc, char * argv[]) {
  assert(argc==3);
  n = atoi(argv[2]);
  m = atoi(argv[1]);

  double (*arr)[n][m] = malloc(sizeof *arr);
  update(n,m,arr);
  return 0;
}

最佳答案

您可以在一维中模拟二维数组,逐行保存数据。这样二维数组: [a,b][c,d] 变为 [a,b,c,d]。为了简单起见,您可以编写一个提供此类功能的包装类。

这是这个想法的演示(不是 100% 防灾,但有效)

#pragma once
#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

typedef int TYPE;

// NOTE: copy consturctor and = operator need to be overloaded as well
template<class T>
struct Matrix
{
    Matrix(int r, int c) : rows(r), cols(c) {
        data = new T[r*c];
    }
    ~Matrix() {
        // As we allocated memory it needs to be freed upon destruction
        delete[] data;
        data = nullptr;
    }
    int rows, cols;
    T* data;
    T* operator[](int row) {
        // Returns pointer to "ROW", further call to [] on result will retrieve item at column in this row
        return data + (row*cols);
    }
};

// Simple cuda kernel 
__global__ void add(TYPE *a, TYPE *b, TYPE *c, int rows, int cols) {
    // Get element row and col
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    // If kernel block/grid is not sized perfectly make sure not to step outside data bounds
    if(row < rows && col < cols)
    {
        int idx = row*cols + col;
        c[idx] = a[idx] + b[idx];
    }
}

int main() {
    // m3 = m1 + m2 using cuda
    int rows = 5, cols = 5, total = rows * cols;
    Matrix<TYPE> m1{ rows,cols }, m2{ rows,cols }, m3{ rows,cols };

    // Initialization as 1D array
    for(int i = 0; i < total; i++)  {
        m1.data[i] = i;
    }

    // Or initialization as 2D array
    for(int r = 0; r < rows; r++)
        for(int c = 0; c < cols; c++)
            m2[r][c] = r*cols + c + 100;

    for(int i = 0; i < total; i++)  std::cout << m1.data[i] << ", ";
    std::cout << "\n";

    for(int r = 0; r < rows; r++) {
        for(int c = 0; c < cols; c++) 
            std::cout << m2[r][c] << ", ";
        std::cout << "\n";
    }

    // CUDA part
    TYPE *d_m1, *d_m2, *d_m3;

    // Allocation
    cudaMalloc((void **) &d_m1, total * sizeof(TYPE));
    cudaMalloc((void **) &d_m2, total * sizeof(TYPE));
    cudaMalloc((void **) &d_m3, total * sizeof(TYPE));

    // Copy m1 and m2 to GPU
    cudaMemcpy(d_m1, m1.data, total * sizeof(TYPE), cudaMemcpyHostToDevice);
    cudaMemcpy(d_m2, m2.data, total * sizeof(TYPE), cudaMemcpyHostToDevice);

    // Oversized on purpose to show row/col guard on add kernel
    dim3 grid(5, 5);
    dim3 block(5, 5);
    add <<< grid, block >>> (d_m1, d_m2, d_m3, rows, cols);

    // Copy result to m3
    cudaMemcpy(m3.data, d_m3, total * sizeof(TYPE), cudaMemcpyDeviceToHost);

    cudaFree(d_m1);
    cudaFree(d_m2);
    cudaFree(d_m3);

    for(int r = 0; r < rows; r++) {
        for(int c = 0; c < cols; c++)
            std::cout << m3[r][c] << ", ";
        std::cout << "\n";
    }

    system("pause");
    return 0;
}

关于c - 你如何在cuda中创建一个二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53513095/

相关文章:

c++ - CUDA C++ 中的友元函数

random - CUDA 的 Mersenne Twister 用于任意数量的线程

c - 在 Sublime Text 3 上运行 Hello World

c - 如何在 Linux 中正确安装 gsl 库?

c - xlib 绘图线不会出现在事件循环之外

cuda - 如何从代码的主机部分获取 GPU 的当前计算能力?

c++ - CUDA Thrust - 计算匹配子数组

c++ - nVidia CUDA 代码不起作用?

c - C中静态结构的成员变量

c - C中的char数组和char指针有什么区别?