0

次のグローバルカーネルがあります。

__global__ void pdegpu(PDE_ParabolicD1_Num_GPU **pdes)
{    
    PDE_ParabolicD1_Num_GPU *loc;
    loc = new PDE_ParabolicD1_Num_GPU();
    loc->Setup();
    delete loc;
    //above code was just an example to show that new and delete work fine

    *pdes = new PDE_ParabolicD1_Num_GPU();   //error occurs here
    (*pdes)->Setup();
}

これを呼び出して、タイプ PDE_ParabolicD1_Num_GPU のオブジェクトを作成し、セットアップします。main() では、同じオブジェクトを使用するため、関数の引数でダブル ポインターを使用しています。main() では、次のことを行います。

PDE_ParabolicD1_Num_GPU pdes_host;
PDE_ParabolicD1_Num_GPU *pdes_dev=0;
pdegpu<<<1,1>>>(&pdes_dev);
cudaStatus = cudaMemcpy(&pdes_host, pdes_dev, sizeof(PDE_ParabolicD1_Num_GPU), cudaMemcpyDeviceToHost);
...
delete [] pdes_dev;

ただし、コードに示されているエラーが表示され、エラーに対する CUDA メモリ チェッカーの出力は次のようになります。

Memory Checker detected 1 access violations.
error = access violation on store (global memory)
gridid = 16
blockIdx = {0,0,0}
threadIdx = {0,0,0}
address = 0x0018f420
accessSize = 4
error MemoryChecker: #misaligned=0  #invalidAddress=1

私が理解している限り、invalidAddressが原因でエラーが発生しています。
誰でも問題を解決するのを手伝ってもらえますか? ありがとうございました

4

2 に答える 2

1

pdes_devホストポインタです。デバイス コードは、ホスト ポインターにアクセスできません。デバイス上で変更可能なポインターを作成する場合は、次のようにします。

PDE_ParabolicD1_Num_GPU **pdes_dev=0;
cudaMalloc((void ***) &(pdes_dev), sizeof(PDE_ParabolicD1_Num_GPU *));
pdegpu<<<1,1>>>(pdes_dev);

カーネル内を使用して割り当てると、デバイス ヒープnewへのポインターが作成されるため、そのようなポインターを操作で使用して、そこに格納されているデータをホストに戻すことはできません。次に、デバイス間のコピーを実行して、カーネルで変更されたデータを、ホストへの転送に適したバッファーに移動する必要があります。したがって、より良い方法は、ホストからオブジェクトにデバイス ストレージ スペースを割り当てることです。cudaMemcpy

PDE_ParabolicD1_Num_GPU *pdes_dev=0;
cudaMalloc((void **) &(pdes_dev), sizeof(PDE_ParabolicD1_Num_GPU));
pdegpu<<<1,1>>>(pdes_dev);

それに応じて、カーネル コードを変更する必要があります。

__global__ void pdegpu(PDE_ParabolicD1_Num_GPU *pdes)
{    

    pdes->Setup();
}

このコードをコンパイルおよびテストしていないため、エラーが発生する可能性がありますが、これは機能すると思われるアプローチの概要です。この質問に対する私の回答にも興味があるかもしれません

于 2013-02-26T21:18:11.220 に答える
1

最初に cudaMalloc を介してメモリを割り当てる必要があります。現在、デバイス コードはホスト メモリに書き込もうとしています。

于 2013-02-26T21:12:08.323 に答える