1

私の質問は次のとおりです。CUDA ハードウェアに障害がありますか、それとも別の説明がありますか? 変更なしで約 1 年間使用されているカーネルがあります。最近、不規則な間隔でセグメンテーション違反が発生し始めました。つまり、数分後、時には数時間の実行後に再現できました。これにより、セグメンテーション違反を再現する最小限のバージョンのプログラムが作成されました。また、stackoverflow の投稿から多くのことを学びました。

cuda-memcheck を繰り返し bash ループで実行すると、最終的に次のように報告されます。

========= Invalid __global__ read of size 4
=========     at 0x000048f0 in SegFault.cu:157:SegFault( float* )
=========     by thread (128,0,0) in block (3706,0,0)
=========     Address 0x003400e8 is out of bounds

悪いポインター操作の通常の犯人は除外されました。もう 1 つの手がかりは、不正なアドレッシングがコード内で発生した場所で一貫していなかったことです。カーネル全体で、グローバル配列へのインデックスに対して不規則に発生していました。

私の質問のこの時点で、最も可能性の高い説明はバグのあるコードです。ハードウェアが故障していると私が信じるに至ったのは、cuda-gdb によるものです。

cuda-gdb ./SegFaultTest
(cuda-gdb) set cuda memcheck on
(cuda-gdb) run
Illegal access to address (@global)0x245684 detected.

Program received signal CUDA_EXCEPTION_1, Lane Illegal Address.
[Switching focus to CUDA kernel 0, grid 1, block (5537,0,0), thread (0,0,0), device 0, sm 22, warp 28, lane 0]
0x00000000004f1ff8 in kernel( float * @global )<<<(33480,1,1),(512,1,1)>>> ( c=0x250000 ) at SegFault.cu:37
37              c[ix] += share_c[0];

(cuda-gdb) print &c[ix]
$2 = (@global float *) 0x255684

インデックス「ix」は次のとおりです。

int ix = blockIdx.x + blockIdx.y*gridDim.x;

そして、インスタンス化後に変更されません。実際、0x245684は の開始アドレスの下にありますc=0x250000。それでも、クエリを実行すると、この配列の許容可能なアドレスである がprint &c[ix]返されます。0x255684再生成には、再度ポップアップする前に 10 ~ 50 回の実行が必要ですが、不正なアドレスは、返さ0x010000れるものと常に 1 ビット異なりprint &c[ix]ます。 エラー メッセージと印刷のアドレスの違いを説明できません。1 ビットの違いと合わせて、ハードウェアの故障が疑われます。FWIW0x010000は、この Tesla C1060 の最大グリッド サイズと同じです。

そしてついに本日CUDAカードを新機種に交換しました。100回実行しても再現できませんでした。

4

1 に答える 1

2

memcheck が有効になっている cuda-gdb が次のような不正なアドレス アクセスを報告した場合:

Illegal access to address (@global)0x245684 detected.

Program received signal CUDA_EXCEPTION_1, Lane Illegal Address.
[Switching focus to CUDA kernel 0, grid 1, block (5537,0,0), thread (0,0,0), device 0, sm 22, warp 28, lane 0]
0x00000000004f1ff8 in kernel( float * @global )<<<(33480,1,1),(512,1,1)>>> ( c=0x250000 ) at SegFault.cu:37
37              c[ix] += share_c[0];

そのアドレスをクエリすると、別の値が返されます。

(cuda-gdb) print &c[ix]
$2 = (@global float *) 0x255684

次に、ハードウェアが壊れます。

于 2015-04-30T11:59:08.000 に答える