GPUのメモリバスは単純に48バイト幅ではありません(2の累乗ではないため、非常に面倒です)。代わりに、それぞれ8バイト(64ビット)の6つのメモリチャネルで構成されます。通常、メモリトランザクションは、メモリのバーストモードを利用するために、チャネル幅よりもはるかに広くなります。適切なトランザクションサイズは64バイトから始まり、サイズ8のバーストを生成します。これは、コンピューティング機能1.xデバイスのハーフワープの16個の32ビットワードとうまく一致します。
128バイト幅のトランザクションはまだ少し高速であり、コンピューティング機能2.0(およびそれ以降)のデバイスのワープ幅の32ビットワードアクセスと一致します。キャッシュラインも128バイト幅で一致します。単一のメモリトランザクションにマップするには、これらのアクセスすべてをトランザクション幅の倍数に揃える必要があることに注意してください。
さて、あなたの実際の問題に関して、おそらく最善のことは何もせず、キャッシュにそれを分類させることです。これは、共有メモリで明示的に行うのと同じように機能しますが、キャッシュハードウェアによって行われ、コードは必要ないため、わずかに高速になります。心配する必要があるのは、各ワープが必要な32×32×4バイト=ワード幅(フロートなど)の場合は4kバイト、ダブルアクセスの場合は8kバイトになるように十分なキャッシュを使用できるようにすることだけです。これは、同時にアクティブになるワープの数を制限して、ワープが互いのキャッシュラインをスラッシングするのを防ぐことが有益な場合があることを意味します。
float2
特別な最適化では、またはのようなベクトルタイプを使用する可能性もあります。これはfloat4
、すべてのCUDA対応GPUに、8バイトまたは16バイトを同じスレッドにマップするロードおよびストア命令があるためです。ただし、コンピューティング機能2.0以降では、各ワープのキャッシュフットプリントがさらに増加するため、一般的な行列転置の場合にそれらを使用する利点は実際にはわかりません。
16kBキャッシュ/48kB共有メモリのデフォルト設定では、SMごとに一度に4つのワープを実行できるため(同時に他のメモリアクセスがない場合)、48kBキャッシュ/を選択するとおそらく有益です。を使用したデフォルトの16kB/48kB分割に対する16kB共有メモリ設定cudaDeviceSetCacheConfig()
。新しいデバイスはより大きなキャッシュを持ち、より多くの異なる分割を提供し、48kBを超える共有メモリの使用を選択します。詳細は、リンクされたドキュメントに記載されています。
完全を期すために、コンピューティング機能3.0で導入されたワープシャッフル命令により、キャッシュや共有メモリを経由せずにワープ内でレジスタデータを交換できることにも言及します。詳細については、CUDACプログラミングガイドの付録B.22を参照してください。
(この付録がないバージョンのプログラミングガイドが存在することに注意してください。したがって、コピーに付録B.13が別のものである場合は、提供されているリンクからリロードしてください)。