1について
warpは非同期で進行します(warp内の32 threadは同期的に動作します)
それを利用して条件分岐が生じる処理を高速化することができます(warp divergenceの削減といいます)
具体的に,サイズが64の配列の奇数番目には1を,偶数番目には0をいれるというタスクを考えます
通常であれば,スレッドIDにインデックスを割り当てると思います
疑似コードは以下
CUDA
1idx = threadIdx.x
2if idx is odd: array[idx] = 1
3else: array[idx] = 0
この場合,奇数番目のスレッドが同時に奇数を処理し,その間他のスレッドは待機しています。その後,偶数番目のスレッドが処理を行います。つまりSM数を考慮しなければ2ステップ必要になります
しかしwarpは非同期で動作するので,カーネル内で, 条件分岐を以下に書き換えることで,1ステップで処理が完了します
CUDA
1warpIdx = idx / 32
2laneIdx = idx % 32
3
4if warpIdx is 0: array[2*laneIdx+1] = 1
5else: array[2*laneIdx] = 0
やっていることは前半のwarpに奇数の処理を,後半のwarpに偶数の処理を割り当てています。warp間は非同期で進行するので,thread間でのifの待機がなくなり,結果1つ目より早く進行します
ちなみに,32というマジックナンバーがどうしても気に入らなければ,warpSizeという予約変数がありますので,書き換えてもよいですが,今のところGPUによって変わらないので32で問題なさそうです
2について
理論上そうなります。できるだけこの処理リソースを生かす方が処理は早くなります(Occupancyを100%に近くする)
しかし実際にはそうはなりません。というのも,最近のCUDAの実行速度のほとんどがメモリアクセス時間であるため,少し凝った処理をしようとすると,1 blockに対し1024 threadではすぐにレジスタとL1キャッシュを使い切り,オフチップであるL2キャッシュにローカル変数が確保されてしまい,結局遅くなります
なので,目安としては1 block に対し, 256 thread か,512 threadと言われています
シェアドメモリは実装上ではブロックでのみ共有されますが,物理的にはSMで共有されているので,二つのblockで一つのSMのシェアードメモリを共有しています
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/20 03:44
2019/09/20 06:03 編集
2019/09/21 08:13
2019/09/23 17:07