C++ 如何在单独的CUDA函数中分配GPU内存?

C++ 如何在单独的CUDA函数中分配GPU内存?,c++,cuda,nvcc,C++,Cuda,Nvcc,我是CUDA的新手,我确信我正在做一些简单到可以修复的事情,但我也不确定到底要搜索什么来找到答案。我试着四处看看,但没用 我的代码中有一些函数,我想用它们来执行矩阵运算,所以我不想编写代码来多次分配内存,而是想用一个函数来完成这项工作。我的问题是内存位置没有被传递回调用我的MatrixInitCUDA函数的函数 如果我直接在矩阵函数中分配内存,它会按预期工作,但我遇到的问题是,我的设备内存指针只分配给MatrixInitCUDA函数中的指针 起初我认为可能有一些类型的参数转换,所以我包括了typ

我是CUDA的新手,我确信我正在做一些简单到可以修复的事情,但我也不确定到底要搜索什么来找到答案。我试着四处看看,但没用

我的代码中有一些函数,我想用它们来执行矩阵运算,所以我不想编写代码来多次分配内存,而是想用一个函数来完成这项工作。我的问题是内存位置没有被传递回调用我的MatrixInitCUDA函数的函数

如果我直接在矩阵函数中分配内存,它会按预期工作,但我遇到的问题是,我的设备内存指针只分配给MatrixInitCUDA函数中的指针

起初我认为可能有一些类型的参数转换,所以我包括了typeinfo头,并在Cudamaloc前后打印出设备参数的类型(没有变化——这并不奇怪)。我已经尝试过为设备矩阵参数传递双指针,但这似乎也不起作用,尽管我不是,但我也做得很好

// Compile using nvcc <file> -lcublas -o <output>
#include <cublas_v2.h>
#include <cuda_runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <typeinfo>

// Define block size for thread allocation
#define BLOCK_DIM 32
#define N 10

typedef struct _matrixSize // Optional Command-line multiplier for matrix sizes
{
    unsigned int A_height, A_width, B_height, B_width, C_height, C_width;
} MatrixSize;

void SetMatrixSize(MatrixSize *matrixSize,
                   unsigned int widthA, unsigned int heightA,
                   unsigned int widthB, unsigned int heightB,
                   unsigned int widthC, unsigned int heightC)
{
    matrixSize->A_height = heightA;
    matrixSize->A_width = widthA;
    matrixSize->B_height = heightB;
    matrixSize->B_width = widthB;
    matrixSize->C_height = heightC;
    matrixSize->C_width = widthC;
}

void MatrixInitCUDA(int argc, char **argv, int &devID, MatrixSize *matrixSize,
                    float *host_matrixA, float *host_matrixB, float *host_matrixC,
                    float *dev_matrixA, float *dev_matrixB, float *dev_matrixC)
{
    // Assign CUDA variables
    devID = 0;
    cudaGetDevice(&devID);
    cudaError_t err;

    // Assign size variables
    size_t matrixA_size = matrixSize->A_height * matrixSize->A_width * sizeof(float);
    printf("Allocation size: %d\tMatrix Size: %d\n", (int) matrixA_size, matrixSize->A_height * matrixSize->A_width);
    size_t matrixB_size = matrixSize->B_height * matrixSize->B_width * sizeof(float);
    size_t matrixC_size = matrixSize->C_height * matrixSize->C_width * sizeof(float);
    printf("PRE ALLOC TYPE: %s\n", typeid(typeof(dev_matrixA)).name());
    // Allocate memory on GPU
    err = cudaMalloc((void **) &dev_matrixA, matrixA_size);
    printf("POST ALLOC TYPE: %s\n", typeid(typeof(dev_matrixA)).name());
    printf("DEV A POST ALLOC: %p\n", dev_matrixA);
    if (err != cudaSuccess) printf("Allocate matrix A: %s\n", cudaGetErrorString(err));
    err = cudaMalloc((void **) &dev_matrixB, matrixB_size);
    if (err != cudaSuccess) printf("Allocate matrix B: %s\n", cudaGetErrorString(err));
    err = cudaMalloc((void **) &dev_matrixC, matrixC_size);
    if (err != cudaSuccess) printf("Allocate matrix C: %s\n", cudaGetErrorString(err));

    // Copy data from host PC to GPU
    err = cudaMemcpy(dev_matrixA, host_matrixA, matrixA_size, cudaMemcpyHostToDevice);
    if (err != cudaSuccess) printf("Copy matrix A to GPU: %s\n", cudaGetErrorString(err));
    err =cudaMemcpy(dev_matrixB, host_matrixB, matrixB_size, cudaMemcpyHostToDevice);
    if (err != cudaSuccess) printf("Copy matrix B to GPU: %s\n", cudaGetErrorString(err));
    err =cudaMemcpy(dev_matrixC, host_matrixC, matrixC_size, cudaMemcpyHostToDevice);
    if (err != cudaSuccess) printf("Copy matrix C to GPU: %s\n", cudaGetErrorString(err));
}

int main(int argc, char **argv)
{
    // Create memory for Layer 1, Layer 2, Layer 3 vectors
    // float *layer1 = malloc(784*sizeof(floats)))
    // Create memory for Weight 1->2, Weight 2->3 matrices

    // Layer 1 will read from file for input (X) values
    // Layer 2 and 3 will be calculated
    int devID = 0;
    cudaGetDevice(&devID);

    // Testing hadamard product, init function, and set matrix size function
    float *host_A, *host_B, *host_C, *dev_A = NULL, *dev_B = NULL, *dev_C = NULL;
    MatrixSize *mallocTest = (MatrixSize *) calloc(sizeof(MatrixSize), 1);
    size_t calcSize = N * N * sizeof(float);
    host_A = (float *) calloc(calcSize, 1);
    host_B = (float *) calloc(calcSize, 1);
    host_C = (float *) calloc(calcSize, 1);
    SetMatrixSize(mallocTest, N, N, N, N, N, N);

    printf("DEV A PRE ALLOC: %p\n", dev_A);

    // Initialize memory on GPU
    MatrixInitCUDA(argc, argv, devID, mallocTest,
                   host_A, host_B, host_C,
                   dev_A, dev_B, dev_C);

    printf("DEV A POST INIT: %p\n", dev_A);
    return 0;
}

有多种方法可以实现所需的行为

方法1 其中一种方法是修改
MatrixInitCUDA
参数以接受设备指针的双指针(
**
),并按如下方式修改代码:

void MatrixInitCUDA(int argc, char **argv, int &devID, MatrixSize *matrixSize,
                    float *host_matrixA, float *host_matrixB, float *host_matrixC,
                    float *&dev_matrixA, float *&dev_matrixB, float *&dev_matrixC)
{
}
修改函数签名:

void MatrixInitCUDA(int argc, char **argv, int &devID, MatrixSize *matrixSize,
                    float *host_matrixA, float *host_matrixB, float *host_matrixC,
                    float **dev_matrixA, float **dev_matrixB, float **dev_matrixC)
{
}
在MatrixInitCUDA中按如下方式分配设备内存:

err = cudaMalloc((void **) dev_matrixA, matrixA_size);
main
调用
MatrixInitCUDA
,如下所示:

MatrixInitCUDA(argc, argv, devID, mallocTest,
                   host_A, host_B, host_C,
                   &dev_A, &dev_B, &dev_C);
方法2 我个人最喜欢的方式是不执行上述任何操作,只修改函数签名以接受设备指针的引用,如下所示:

void MatrixInitCUDA(int argc, char **argv, int &devID, MatrixSize *matrixSize,
                    float *host_matrixA, float *host_matrixB, float *host_matrixC,
                    float *&dev_matrixA, float *&dev_matrixB, float *&dev_matrixC)
{
}

谢谢我知道这件事太简单了。我把头撞在墙上太久了,想都不敢想。