銀行間紛争とは何ですか?(Cuda / OpenCLプログラミングを行う)


95

私はCUDAとOpenCLのプログラミングガイドを読んでいますが、銀行の競合とは何なのかわかりません。彼らは、主題そのものについて詳しく説明することなく、問題を解決する方法を説明します。誰かがそれを理解するのを手伝ってくれる?ヘルプがCUDA / OpenCLのコンテキストにあるのか、コンピュータサイエンスにおける一般的な銀行の紛争にすぎないのかは、私には好みがありません。

回答:


105

nvidia(およびその問題のamd)gpusの場合、ローカルメモリはメモリバンクに分割されます。各バンクは一度に1つのデータセットしかアドレス指定できないため、ハーフワープが同じバンクとの間でデータをロード/ストアしようとすると、アクセスをシリアル化する必要があります(これはバンクの競合です)。gt200 gpusの場合、16バンク(fermiの場合は32バンク)、AMD gpusの場合は16または32バンク(57xx以上:32、以下はすべて16))であり、32ビットの粒度でインターリーブされています(バイト0-3はバンク1のバンク1、4〜7、バンク2、...、64〜69など)。より良い視覚化のために、それは基本的に次のようになります:

Bank    |      1      |      2      |      3      |...
Address |  0  1  2  3 |  4  5  6  7 |  8  9 10 11 |...
Address | 64 65 66 67 | 68 69 70 71 | 72 73 74 75 |...
...

したがって、ハーフワープの各スレッドが連続する32ビット値にアクセスする場合、バンクの競合はありません。このルールの例外(すべてのスレッドは独自のバンクにアクセスする必要があります)はブロードキャストです。すべてのスレッドが同じアドレスにアクセスする場合、値は1回だけ読み取られ、すべてのスレッドにブロードキャストされます(GT200の場合、ハーフワープにアクセスするすべてのスレッドである必要があります。同じアドレス、iirc fermiおよびAMD gpusは、同じ値にアクセスする任意の数のスレッドに対してこれを実行できます)。


3
ビジュアルと説明に感謝します。ブロードキャストについて知らなかったので、それは重要な情報のようです:)ロードとストアが共有メモリでバンクの競合を引き起こしていないことを確認するにはどうすればよいですか?どういうわけかアセンブリコードに到達する必要がありますか、それとも他の方法がありますか?
smuggledPancakes

3
バンク競合の発生は、実行時に決定されるものと思われるため(実行時にほとんどすべてのアドレスが生成された後、コンパイラーはそれを認識しないことを意味します)、コンパイルされたバージョンを取得してもあまり役に立ちません。私は通常、これを昔ながらの洗練された方法で行い、ペンと紙を持って、コードがどこに格納されているかを考え始めます。結局のところ、銀行紛争の発生を管理するルールはそれほど複雑ではありません。それ以外の場合は、nvidia OpenCLプロファイラーを使用できます(sdk、iircにバンドルする必要があります)。ワープシリアライズ用のカウンターがあると思います。
Grizzly

1
ワープのシリアル化を指摘していただきありがとうございます。計算プロファイラが付属してREADMEテキストファイルの1つが、このことを言った
smuggledPancakes

1
上のコメントを失礼しました。何らかの理由で再編集できません。とにかく、これはコンピューティングプロファイラーのreadmeにある「warp_serialize:共有メモリまたは定数メモリへのアドレスの競合でシリアル化するスレッドワープの数」で見つかりました。これは、プロファイラーの出力を見るだけで競合があるかどうかを簡単に確認できる点で優れています。ペンと紙に銀行の競合があるかどうかをどのように判断しますか。例やチュートリアルから学びましたか?
smuggledPancakes

1
先ほど述べたように、アドレスから銀行へのマッピングは比較的単純なので、どのアクセスがどの銀行に行くのか、したがって銀行の競合があるかどうかを判断するのはそれほど難しくありません。この論文は、より多くの紛争へのアクセスパターンのためのものであり、私はそれなしではそれを行うことができません。
Grizzly

13

並行してアクセスできる共有メモリは、モジュール(バンクとも呼ばれます)に分割されます。同じバンクで2つのメモリロケーション(アドレス)が発生すると、バンクの競合が発生し、その間にアクセスがシリアルで行われるため、パラレルアクセスの利点が失われます。


これは、ハーフワープがメモリを保存またはロードするタイミングに関連していますか?16のスレッドがメモリトランザクションを実行しようとするため、複数のスレッドで同じバンクにアクセスすると、シリアル化された処理が発生しますか?また、同じバンクにデータを格納/ロードしないことをどのように確認しますか?
smuggledPancakes

10

簡単に言うと、バンク競合は、メモリアクセスパターンがメモリシステムで使用可能なバンク間でIOを分散できない場合です。次の例は、その概念を詳しく説明しています。

2次元の512x512整数配列があり、DRAMまたはメモリシステムには512バンクがあるとします。デフォルトでは、配列データは、arr [0] [0]がバンク0に、arr [0] [1]がバンク1に、arr [0] [2]がバンク2に行くようにレイアウトされます。 arr [0] [511]はバンク511に移動します。arr[x] [y]を一般化するには、バンク番号yを使用します。これで、いくつかのコード(以下に示す)が列メジャー方式でデータにアクセスし始めます。yを一定に保ちながらxを変更すると、最終的な結果として、連続するすべてのメモリアクセスが同じバンクにヒットするため、バンクの競合が発生します。

int arr[512][512];
  for ( j = 0; j < 512; j++ ) // outer loop
    for ( i = 0; i < 512; i++ ) // inner loop
       arr[i][j] = 2 * arr[i][j]; // column major processing

このような問題は、通常、配列をバッファリングするか、配列内の素数の要素を使用することにより、コンパイラによって回避されます。


7

(CUDA Bank Conflict)これがお役に立てば幸いです。これは非常に良い説明です...

http://www.youtube.com/watch?v=CZgM3DEBplE


1
リンクのみの回答は推奨されないことに注意してください。SOの回答は、ソリューションの検索のエンドポイントである必要があります(時間の経過とともに陳腐化する傾向がある参照の停止に対するもの)。参照としてリンクを維持しながら、ここにスタンドアロンの概要を追加することを検討してください。
kleopatra 2013年

OPをよりよく支援するために、リンクについて詳しく説明してください。
Peter Foti 2013年

1
このビデオは本当に役に立ちます!そして、なぜ反対票を投じるのかわかりません!とても良い入力です!+1
ガブリエル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.