CUDA プログラミングに関する注意事項 (3)


序文

CUDA プログラム実行時のエラー検出

1.CUDAプログラム実行時のエラー検出

不正なヘッダー ファイルを検出する

一部のログ ファイルと同様に、一般的なエラー検出では、エラー検出 API を実行するためのコードを含むヘッダー ファイルが書き込まれます。cuda基本プログラムapiの動作エラー検出では、基本的にすべてのcuda apiの戻り値に、正常に使用されたかどうかのcudaError_t構造体のフラグ情報があり、呼び出しが成功するとcudaSuccessが返されることがわかりました。したがって、戻り値に応じて、ヘッダー ファイルにマクロ関数を定義して、cuda プログラムが正しく実行されていないかどうかを確認できます。

#pragma once
#include<stdio.h>

#define CHECK(call) \
do                  \
{
      
      \
    const cudaError_t error_code = call; \
    if(error_code != cudaSuccess) \   
    {
    
    \
        printf("cuda error"); \
        printf("  File:   %s\n",__FILE__); \
        printf("  Line:   %d\n",__LINE__); \
        printf("  Error code: %d\n",error_code); \
        printf("  Error text: %s\n",cudaGetErrorString(error_code)); \
        exit(1); \
    }\
} while(0)

(1) #pragma once は前処理命令であり、条件付きコンパイル コマンド #ifndef と同じ機能ですが、より簡潔です。
(2) マクロ関数 CHECK のパラメータは、cuda ランタイム API 関数です。
(3) プリコンパイラには定義済みのマクロがあります。

    __FILE__ // 获取当前文件名
    __func__ // 获取当前函数名
    __LINE__ // 获取当前行号
    __DATE__ // 获取当前日期
    __TIME__ // 获取当前时间
    __WORDSIZE // 获取当前编译器的位数,适合用来显示警告、错误信息。

(4) マクロ関数内で do while 文を使用しないことも可能ですが、安全でない場合があります。マクロ機能を使用すると、コンパイルおよびソースコードへのインポート時に自動的にセミコロンが追加されるため、 while (0) の後にセミコロンを追加する必要はありません

実行時に CUDA API 関数を確認する

書き込まれたヘッダー ファイルをソース プログラムにインクルードします。cuda プログラム ヘッダー ファイル名は、通常 xxx.cuh という名前です。次のように、ヘッダー ファイルの CHECK マクロ関数にパラメーターとして cuda ランタイムを呼び出す api 関数を渡すだけです。

    // 分配设备内存
    double *d_x,*d_y,*d_z;
    // printf("%p",d_x);
    CHECK(cudaMalloc((void **)&d_x,M));
    CHECK(cudaMalloc((void **)&d_y,M));
    CHECK(cudaMalloc((void **)&d_z,M));
    // 将某些数据从主机复制到设备上
    CHECK(cudaMemcpy(d_x,h_x,M,cudaMemcpyHostToDevice));
    CHECK(cudaMemcpy(d_y,h_y,M,cudaMemcpyHostToDevice));

    // 数组求和
    const int block_size = 128;
    const int gride_size = N/block_size;
    add<<<gride_size,block_size>>>(d_x,d_y,d_z);
    CHECK(cudaMemcpy(h_z,d_z,M,cudaMemcpyHostToDevice));

プログラムがエラーを報告した場合、次の情報が表示されます。
ここに画像の説明を挿入

実行時に CUDA カーネル関数をチェックする

カーネル関数には戻り値がないため、上記のメソッドを上記のように直接使用することはできません。cuda の api には、カーネル関数で発生する可能性のあるエラーをキャッチする方法があります。
cudaGetLastError():
ここに画像の説明を挿入
注: この関数は、以前の非同期開始のエラー コードを返す場合もあります。
したがって、後で確認するときは、次のようにホストとデバイスが同期されているかどうかも確認してください。

    // 数组求和
    const int block_size = 1240;  // 最大限制是1024
    const int gride_size = N/block_size;
    add<<<gride_size,block_size>>>(d_x,d_y,d_z);
    // 检查核函数的调用
    CHECK(cudaGetLastError());
    CHECK(cudaDeviceSynchronize());  // 可用可不用,后面的隐式的起到了同步主机与设备的作用
    // 将某些数据从设备复制到主机上,这个数据传输函数隐式的起到了同步主机与设备的作用,所以后面用不用cudaDeviceSynchronize都可以
    CHECK(cudaMemcpy(h_z,d_z,M,cudaMemcpyDeviceToHost));
    check(h_z,N);

表示された同期ホストとデバイスの cudaDeviceSynchronize() を使用すると、エラーの場所がより正確になります。
間違ったエラー メッセージを確認します。
ここに画像の説明を挿入

CUDA-MEMCHECKツール

cuda は、cuda-memcheck コマンドによってメモリ エラーをチェックするために使用される CUDA-MEMCHECK のツール セットを提供します。
-h を使用すると、メモリをチェックする主な項目は次のとおりです。
ここに画像の説明を挿入

要約する

cudaプログラムのエラーチェックの基本的な方法
参考:
ブログの内容が著作権を侵害している場合は、連絡してすぐに削除できます!
CUDA プログラミング: 基本と実践
https://docs.nvidia.com/cuda/
https://docs.nvidia.com/cuda/cuda-runtime-api
https://github.com/brucefan1983/CUDA-Programming

おすすめ

転載: blog.csdn.net/weixin_41311686/article/details/128720882
おすすめ