合体グローバルメモリを理解しようとしています。
奇数の float のセットをグローバル メモリにロードしたいとします。各スレッドは、3 つの float のセットを処理します。これらのフロートが A、B、および C であるとします。
A0, B0, C0
A1, B1, C1
A2, B2, C2
..
A19, B19, C19
したがって、スレッドは次のようにデータを取得します。
Thread 0: A0, B0, C0
Thread 1: A1, B1, C1
Thread 2: A2, B2, C2
..
Thread 19: A19, B19, C19
最初のアプローチ: 次
の 3 つの配列をロードできます:float A[20]; float B[20]; floatC[20];
データをグローバル メモリにロードするには、cudaMemcpy() を 3 回実行する必要があります。このアプローチは、おそらくうまく合体しないでしょう。
2 番目のアプローチ:
より良いアプローチは次のようなものです。
struct {float A, float B, float C} dataPt;
dataPt data[20];
1 つの cudaMemcpy() でデータをロードできましたが、メモリ アクセスがうまく合体するかどうかはわかりません。
3 番目のアプローチ:
struct {float A, float B, float C, float padding} dataPt2;
dataPt2 data2[20];
また
struct __align__(16){float A, float B, float C} dataPt3;
dataPt3 data3[20];
単一の cudaMemcpy() でデータをグローバル メモリにロードでき、データへのスレッド アクセスが結合されます。(無駄なグローバル メモリを犠牲にして。)
1) 各スレッドが入力データをロードするためにおそらく 3 つのバス サイクルを必要とするため、最初のアプローチは合体しません。
2) 2 番目のアプローチは多くのスレッドを結合しますが、入力データを取得するために 2 つのバス サイクルを必要とするスレッドがいくつかあります。
3) 3 番目のアプローチでは、すべてのスレッドが合体します。
これは正確ですか?2番目と3番目のアプローチに大きな違いはありますか? 3 つのスレッド ディメンション (threadIdx.x、threadIdx.y、threadIdx.z) を使用するアプローチはありますか?