0

私のプログラムは、3D 配列として表され、LabView から私のプログラムに送信されるビデオ ファイルを分析します。LabView は既にこの 3 次元配列を 1 次元配列にフラット化しているため、CUDA で 1 次元配列を割り当て、cudaMalloc を使用し、cudaMemcpy を使用してデータをコピーしました。しかし、2XXX を超える 120x240 ピクセル画像を送信している場合、いくつかの cuda メモリ関数 (cudamemcpy と cudafree は、いくつかのカーネルが呼び出された後にプログラムで発生します) から「不明なエラー」が発生していることに気付きました。これらは最終的に私のプログラムを壊します。ただし、画像を送信する場合は数値を下げても問題ありません。これにより、自分のコードは問題ないのに、メモリ割り当ての方法が間違っていると思い込んでしまいます。

まず、ピッチドメモリーについて話しましょう。私の知る限り、線形データが 2 つのチャンクに分割されないようにメモリを割り当てるのに適切なサイズを選択することがすべてです。これは、2 次元および 3 次元の配列で特に一般的です。これは、高速アクセスのために行または列をメモリ内に保持する必要があるためです。

ピッチドメモリーを使用しないと、このような問題が発生する可能性はありますか? ピッチド メモリを使用しない場合、特にこれらの非常に大きな配列の場合、どのような種類のエラーが発生する可能性がありますか? この時点まで、cudaMallocPitch と cudaMalloc3d を使用するオプションを無視してきましたが、技術的には 2 次元と 3 次元の配列を持っていて、それらをフラット化しました。

最後に、cudaGetLastError が「不明なエラー」しか通知しない場合、コードの問題をさらにデバッグするにはどうすればよいですか? どの関数に問題があるかを見つけることはできますが、cudaFree のようなものである場合、この種のものをデバッグしたり、問題の原因を突き止めたりする方法はありません。

とにかく、助けてくれてありがとう。

4

1 に答える 1

2

ピッチド メモリを使用しないことの代償は速度です。2 つのスレッドがビデオの隣接するフレームにアクセスしようとし、フレームが連続したメモリに (位置合わせなしで) 割り当てられている場合、1 つのフレームの一部が他のフレームと同じメモリ ブロックまたはキャッシュ ラインに存在し、1 つのスレッドが他のスレッドがメモリ操作を完了するまで待ちます。おそらく致命的ではありませんが、間違いなく最適ではありません。そこには、書き込み後読み取りまたは書き込み後書き込みの問題もある可能性があります。

ピッチ メモリを使用するコストは、要素 (フレームまたはスキャンライン) のサイズが優先配置境界の偶数倍でない場合、メモリ割り当てがわずかに増加することです。次のフレームまたはスキャンラインの開始は、適切なメモリ アドレス境界で開始するために、数バイトのパディングが必要になる場合があります。各フレームまたはスキャンライン サイズに 30 バイトを追加して、2000 フレームの適切な境界の次を取得すると、合計メモリ割り当てに約 60,000 バイトが追加されます。

データ セット全体がデバイス メモリに収まらない場合は、データセットを小さなチャンクに分割し、cuda カーネルを複数回呼び出して各チャンクを処理する必要があります。コードが常にデータ セット全体にランダム アクセスする必要がない場合は、ストリーミング モデルに切り替えると、全体的な処理時間が大幅に短縮される可能性があります。1 つのワープがそのデータ チャンクがデバイス メモリに読み込まれるのを待っている間、別のワープがそのチャンクを処理している可能性があるため、CUDA コアがアイドル状態になることはありません。

ビデオ処理コードが作業を行うために、たとえば 4 つの連続するフレーム バッファーを参照する必要がある場合、不要になったときに最も古いフレームをキューから削除し、新しいフレームを設定するバッファー管理システムを作成できます。次のカーネル呼び出しの準備。さらに良いことに、メモリ割り当てのオーバーヘッドを回避するために、古いフレーム メモリを新しいフレーム用にリサイクルします。

実際に必要なときに (または直前に) 必要なものだけをロードします。これは、20 ドルのビデオ プレーヤーおよびレコーダー チップが、わずかな実際の RAM で数ギガバイトのビデオ ストリームをリアルタイムで処理する方法です。

于 2012-08-15T21:35:49.110 に答える