2017-11-19 10 views
2

私はCUDAを使い始めましたが、私は修正するだけの簡単なことをしていることを確信していますが、答えを見つけるために正確に何を探すべきかも分かりません。私は周りを見回してみたが役に立たなかった。別のCUDA関数でGPUメモリをどのように割り当てるのですか?

私はコードでいくつかの関数を使用して行列演算を行いたいので、メモリを何回も割り当てるコードを書くのではなく、私のために関数を使いたいと思います。私の問題は、メモリ位置が私のMatrixInitCUDA関数を呼び出す関数に戻されていないことです。

メモリを行列関数に直接割り当てると、期待通りに動作しますが、私が実行している問題は、デバイスメモリへのポインタがMatrixInitCUDA関数内のポインタに割り当てられているということです。

最初に私は引数の型変換があったかもしれないと思ったので、typeinfoヘッダーを組み込み、cudaMallocの前と後にデバイス引数の型を出力しました(変更なし - 驚くことではありません)。私は、デバイスの行列の引数のためのダブルポインタを渡してみましたが、それはいずれか正しく動作していませんが、いずれか動作していないようです。

// 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; 
} 

ここで私がコンパイルし、このコードを実行する場合、私が得る出力です:

DEV A PRE ALLOC: (nil) 
Allocation size: 400 Matrix Size: 100 
PRE ALLOC TYPE: Pf 
POST ALLOC TYPE: Pf 
DEV A POST ALLOC: 0x10208400000 
DEV A POST INIT: (nil) 

答えて

2

望ましい行動を達成することができる使用して、複数の方法があります。

方法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) 
{ 
} 

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) 
{ 
} 
+0

ありがとう!私はそれがあまりにも単純な方法であることを知っていた。私は思考するにはあまりにも長い間、頭を壁に打ち付けていた。 –

関連する問題