私が知っていることに基づいて、ワープのスレッドがグローバルメモリ内の同じアドレスにアクセスすると、リクエストがシリアル化されるため、定数メモリを使用することをお勧めします。GPU に L1 および L2 キャッシュ レベル (Fermi および Kepler アーキテクチャ) が装備されている場合、同時グローバル メモリ アクセスのシリアル化は行われますか? つまり、ワープのスレッドが同じグローバル メモリ アドレスにアクセスする場合、1 つのスレッドが既にそのアドレスを要求しているため、ワープの 31 のスレッドはキャッシュの存在の恩恵を受けますか? アクセスが読み取りであり、アクセスが書き込みである場合はどうなりますか?
1 に答える
Fermi と Kepler の同じワープ内のスレッドによる同じアドレスへの同時グローバル アクセスは、シリアル化されません。ワープ読み取りには、パフォーマンスに影響を与えずに単一のキャッシュライン読み取りからのすべての読み取りを満たすブロードキャスト メカニズムがあります。パフォーマンスは、完全に結合された読み取りの場合と同じです。これは、キャッシュの詳細に関係なく当てはまります。たとえば、L1 キャッシュが無効になっている場合でも当てはまります。
同時書き込みのパフォーマンスは指定されていませんが(AFAIK)、動作的には、同時書き込みは常にシリアル化され、順序は未定義です。
以下の追加の質問に答える編集:
- ワープ内のすべてのスレッドが同じ値を同じアドレスに書き込んでも、シリアル化されますか? そのような状況を認識する書き込みブロードキャストメカニズムはありませんか?
すべての同時書き込みを調べて、それらがすべて同じかどうかを確認し、それに基づいて何らかのアクションを実行する書き込みブロードキャスト メカニズムはありません。正解は、書き込みが不特定の順序で行われ、パフォーマンス特性が定義されていないことです。明らかに、書き込まれているすべての値が同じである場合、最終的にその場所にある値はその値になると確信できます。ただし、書き込みアクティビティが単一のサイクルに折りたたまれているのか、それとも完了するのに複数のサイクルが必要なのかを尋ねている場合、その実際の動作は未定義 (文書化されていない) であり、実際にはアーキテクチャごとに異なります (たとえば、cc1.x は、すべての書き込みが実行されるようにすべての方法でシリアル化することができますが、cc2.x は、1 つの書き込みが「勝ち」、他のすべての書き込みが実行されるように「シリアル化」することができます)。破棄され、実際のサイクルは消費されません。) 繰り返しますが、パフォーマンスは文書化されておらず、指定もされていませんが、プログラムで観察可能な動作は定義されています。
2 このブロードキャスト メカニズムでは、コンスタント メモリ ブロードキャスト アクセスとグローバル メモリ ブロードキャスト アクセスの唯一の違いは、前者はアクセスをグローバル メモリまでルーティングする可能性があることですが、後者は専用のハードウェアを備えているため高速ですよね?
__constant__
メモリは、SM ごとに使用できる専用のハードウェアであるコンスタント キャッシュを使用し、グローバル メモリの特定のセクションを読み取り専用でキャッシュします。ファッション。この HW キャッシュは、L1 キャッシュ (存在し、有効になっている場合) および L2 キャッシュから物理的および論理的に分離されています。Fermi 以降では、どちらのメカニズムも読み取り時のブロードキャストをサポートしており、定数キャッシュではサイクルごとに 1 つの読み取りアクセスしか処理できない (つまり、ワープによるキャッシュライン全体の読み取りをサポートしていない) ため、これが推奨されるアクセス パターンです。どちらのメカニズムも、キャッシュ (存在する場合) で「ヒット」するか、「ミス」してグローバル読み取りをトリガーする可能性があります。特定の場所 (またはキャッシュライン) の最初の読み取りで、どちらのキャッシュにも要求されたデータがあるため、「ミス」してグローバル メモリの読み取りをトリガーし、アクセスを処理します。その後、いずれの場合も、関連するデータがその間に追い出されないと仮定して、後続の読み取りはキャッシュから処理されます。初期の cc1.x デバイスの場合、これらの初期のデバイスには L1 キャッシュがなかったので、コンスタント メモリ キャッシュは非常に価値がありました。Fermi以降の場合、定数キャッシュを使用する主な理由は、識別可能なデータ(つまり読み取り専用)とアクセスパターン(ワープごとに同じアドレス)が利用可能な場合であり、定数キャッシュを使用すると、それらの読み取りがL1を通過するのを防ぎ、おそらく他のデータの削除。実際には、L1 が単独でサポートできるものを超えて、キャッシュ可能なフットプリントをいくらか増やしています。次に、定数キャッシュを使用すると、これらの読み取りが L1 を通過し、他のデータが削除される可能性がなくなります。実際には、L1 が単独でサポートできるものを超えて、キャッシュ可能なフットプリントをいくらか増やしています。次に、定数キャッシュを使用すると、これらの読み取りが L1 を通過し、他のデータが削除される可能性がなくなります。実際には、L1 が単独でサポートできるものを超えて、キャッシュ可能なフットプリントをいくらか増やしています。