2017-09-12 14 views
0

私は、ローカルメモリに収まらない大きすぎるフラグのバッファを使用する画像処理カーネルを持っています。フラグは、予測可能なラスターパターン(左上から右下)でアクセスされます。ローカル/共有メモリをグローバルキャッシュとして使用する

私の考えは、グローバルメモリにフラグを格納し、ローカルメモリをグローバルのキャッシュとして使用することです。ですから、私はラスターパターンに沿って進んでいくうちに、グローバルからローカルへのフラグを読み込み、何らかの処理をしてから、フラグをグローバルに書き戻したいと思います。しかし、私は関与するレイテンシを隠したい。だから、

、私は場所のシリーズとしての私のイメージにアクセスするとします。a1,a2,a3...... 私は次の操作を行いたい:

  1. a1フラグ
  2. をフェッチa2フラグがフェッチされている間a2フラグ
  3. をフェッチします、プロセスa1を保存して、 をグローバルメモリに保存します
  4. フェッチa3のフラグ
  5. a3フラグがフェッチされている間、プロセスa2場所とバック グローバルメモリに保存
  6. など

どのように私は待ち時間が隠されていることを確認するために私のコードを構築する必要がありますか? これを行うにはvload/vstoreを使用する必要がありますか?または、GPUハードウェア は、自動的にレイテンシー隠蔽を行いますか?

+0

['barrier'](https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/barrier.html)を使ってみましたか? –

+0

'barrier'は、すべての作業項目がカーネル内の特定のポイントに到達してから進むことを許可するために必要です。しかし、これはメモリトランザクションの待ち時間に影響しません。 – Jacko

答えて

1

重要なのは、読み取りが合体することを確認することです。これがピークメモリ帯域幅を取得する唯一の方法です。次に、すべての計算がメモリアクセスの背後に隠れていることを確実にするために、占有率が十分に高くなるように、カーネルの複雑さを十分に低く保ちます。その後、できるだけ早く実行されます。

2

手動で行う必要はありません。 GPUデバイスが既にこれを行います。

ワークアイテムの一部がバッチ(ワープ)で実行され、グローバルメモリを待ってバッチを続行できない場合は、別のバッチをその時間内に起動し、そのバッチをスリープ状態にします。

+0

ありがとうございます。私がこれについて尋ねる理由は、私がすでにこれをやろうとしたことで、私のパフォーマンスはひどいものでした。だから、私はコードを再構成して、レイテンシー隠蔽をより有効に活用したいと考えています。 – Jacko

+0

重要な点は、読み込みが合体していることを確認することです。これがピークメモリ帯域幅を取得する唯一の方法です。次に、すべての計算がメモリアクセスの背後に隠れていることを確実にするために、占有率が十分に高くなるように、カーネルの複雑さを十分に低く保ちます。その後、できるだけ早く実行されます。 – Dithermaster

+0

ありがとう、@Dithermaster。これを回答として入力して受け入れます。 – Jacko

2

CUDA Surfaceのコンセプトは、あなたのケースに適したツールです。アクセスパターンは画像処理用に最適化されており、テクスチャキャッシュを使用しているため、キャッシュを自分で実行する必要はありません。テクスチャキャッシュはブロック単位であるため、1つのブロックで小さな四角形を処理するために2Dスレッド分布を使用することができます。

隠蔽レイテンシは、ハードウェアより多くのスレッドとブロックを同時に処理できるようにスケジューリングすることによって自然に行われます。デバイスのCompute Capabilityに応じて、「マルチプロセッサあたりの常駐スレッドの最大数」(CC 3.0以降2048)とSMごとのCUDAコアの数の比は、スレッドの総数を計算するためのヒントです(スレッド*ブロック)、レイテンシを最大限に隠すようにスケジューリングします。最適値は実際にはコード自体、カーネルが必要とするレジスタの数などによって決まることに注意してください。

1

あなたは、非常に効率的なカーネルを持つためのすべての要件を持っているように見えます。 データアクセスパターン、gmemからの合体読み取りを予測することはできますが、複雑な処理があります。

ので、ハードウェアは失速し、反りが値をロードしているが、あなたはelegible縦糸の多くすることが必要がありますが処理する「飛行中」常駐ブロックで縦糸を選ぶことによって、自動的にグローバル負荷lattencyを非表示になります。私はあなたがここに2つのシャロンを扱うことを考える:

  • 何の十分なスレッド/ブロック(あなたが低占有を有していてもよい)ハードウェアは文句を言わないしばらくを処理する準備ができているの経糸を選択することができることを意味している はありませんもう一つのワープはグローバルからの値をロードしています(カーネルが起動するにはあまりにも多くのリソースを使用していても起こる可能性があるので、一度に処理できるのはわずかです。
  • 並列処理では十分ではないので、大きなアクセスパターンがあっても、カーネルには「シーケンシャル」処理がたくさんあるか、実行依存性があるか、または多くの同期化があるため、ワープは値飛行中のすべてのワープが停止しているため、実行する処理が多くてもパフォーマンスが低下する可能性があります。

あなたが持っているものを知ることは非常に難しいです。しかし、いくつかの実験があなたを助けることができます。 Achieved OccupancyInstruction StatisticsBranch StatisticsIssue Efficiencyは、カーネルの制限を特定するのに役立ちます。 processo pipeline limitationでバンプすることさえできます。

"ローカル"メモリはオフチップ(グローバルメモリ)であるが、一部のハードウェアではL1にキャッシュできるようになっていることに注意してください。あなたは処理を改善するために共有メモリを使用することさえあるように見えます。example

基本的に、80%以上のワープがある限り、レイテンシを隠す問題はありません。

関連する問題