2

このコードでは、CUDA を使用して GPU で float の 1D 配列を生成しています。数値は 0 から 1 の間です。私の目的では、-1 から 1 の間である必要があるため、各要素を 2 倍してから 1 を減算する単純なカーネルを作成しました。しかし、ここで何かがうまくいかない。元の配列を .bmp に出力すると、http://i.imgur.com/IS5dvSq.png (典型的なノイズ パターン) が得られます。しかし、カーネルでその配列を変更しようとすると、空白の黒い画像http://imgur.com/cwTVPTGが表示されます。プログラムは実行可能ですが、デバッグでは次のようになります。

Midpoint_CUDA_Alpha.exe の 0x75f0c41f での初回例外: Microsoft C++ 例外: cudaError_enum のメモリ位置 0x003cfacc..

Midpoint_CUDA_Alpha.exe の 0x75f0c41f での初回例外: Microsoft C++ 例外: cudaError_enum のメモリ位置 0x003cfb08..

Midpoint_CUDA_Alpha.exe の 0x75f0c41f での初回例外: Microsoft C++ 例外: [rethrow] at memory location 0x00000000..

この件に関して、何か助けやヒントがあれば幸いです。ありがとう !(編集)

#include <device_functions.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include "EasyBMP.h"
#include <curand.h> //curand.lib must be added in project propetties > linker > input
#include "device_launch_parameters.h"

float *heightMap_cpu;
float *randomArray_gpu;
int randCount = 0;
int rozmer = 513;

void createRandoms(int size){
    curandGenerator_t generator;
    cudaMalloc((void**)&randomArray_gpu, size*size*sizeof(float));
    curandCreateGenerator(&generator,CURAND_RNG_PSEUDO_XORWOW);
    curandSetPseudoRandomGeneratorSeed(generator,(int)time(NULL));
    curandGenerateUniform(generator,randomArray_gpu,size*size);
}

__global__ void polarizeRandoms(int size, float *randomArray_gpu){
    int index = threadIdx.x + blockDim.x * blockIdx.x;
    if(index<size*size){
        randomArray_gpu[index] = randomArray_gpu[index]*2.0f - 1.0f;
    }
}

//helper fucnction for getting address in 1D using 2D coords
int ad(int x,int y){
    return x*rozmer+y;
}

void printBmp(){
    BMP AnImage;
    AnImage.SetSize(rozmer,rozmer);
    AnImage.SetBitDepth(24);
    int i,j;
    for(i=0;i<=rozmer-1;i++){
        for(j=0;j<=rozmer-1;j++){
            AnImage(i,j)->Red = (int)((heightMap_cpu[ad(i,j)]*127)+128);
            AnImage(i,j)->Green = (int)((heightMap_cpu[ad(i,j)]*127)+128);
            AnImage(i,j)->Blue = (int)((heightMap_cpu[ad(i,j)]*127)+128);
            AnImage(i,j)->Alpha = 0;
        }
    }
    AnImage.WriteToFile("HeightMap.bmp");
}

int main(){
    createRandoms(rozmer);
    polarizeRandoms<<<((rozmer*rozmer)/1024)+1,1024>>>(rozmer,randomArray_gpu);
    heightMap_cpu = (float*)malloc((rozmer*rozmer)*sizeof(float));
    cudaMemcpy(heightMap_cpu,randomArray_gpu,rozmer*rozmer*sizeof(float),cudaMemcpyDeviceToHost);
    printBmp();

    //cleanup
    cudaFree(randomArray_gpu);
    free(heightMap_cpu);
    return 0;
}
4

1 に答える 1

3

これは間違っています:

cudaMalloc((void**)&randomArray_gpu, size*size*sizeof(float));

変数では使用cudaMallocしません。__device__適切なcudaエラーチェックを行うと、その行がエラーをスローすると確信しています。

この方法でポインターを本当に使用したい場合は__device__、別の通常のポインターを作成する必要がありますcudaMalloc。次に、次を使用してポインター値をデバイスポインターにコピーしますcudaMemcpyToSymbol

float *my_dev_pointer;
cudaMalloc((void**)&my_dev_pointer, size*size*sizeof(float));
cudaMemcpyToSymbol(randomArray_gpu, &my_dev_pointer, sizeof(float *));

CUDA プログラムで問題が発生した場合は常に、適切な cuda エラー チェックを行う必要があります。何が悪いのかに注意を向ける可能性があります。

そして、はい、カーネルは、変数がパラメーターとして明示的にカーネルに渡されなくても、変数にアクセスできます。__device__

プログラミング ガイドでは、変数の適切な使用法と__device__、ホストからそれらにアクセスするために使用する必要がある API 関数について説明します。

于 2013-09-11T05:03:34.560 に答える