ComputeShaderでモブを動かす【その6:二次元スレッド・複カーネル化/効果なし】Unity3DUnityComputeShader経緯コンピュートシェーダー(ComputeShader)を学ぶため、自動車を動かす交通シミュレーターもどきを作ってみようと思いました。個々の自動車がそれぞれ衝突を回避しつつ適切な経路で目的地に移動できるようになるのが目標です。200台に満たない程度でも時々カクつくのが気になりました(上のキャプチャは170台前後で推移)。そこでシェーダーのスレッドグループをチューニングしてパフォーマンス向上できないか試してみました。コードはいままでの分も含め全てGithubにあります。修正方針ずっと気になってたのはこの部分です。車のindexとして使用していますが、下のfor文で全部の車に対して衝突予測を繰り返しています。回したら、シェーダーが本領発揮できるんじゃないかと思いました。idMin);※↑あくまでイメージです。複数カーネル化の修正にあたって、下記記事を参考にさせていただきました。パーティクルを作ってみた】http://tips.hecomi.com/entry/2016/05/08/160626構造体の修正カーネル間で情報を渡すため、フィールドを追加しました。デバッグ目的で以前から入れてましたが、ロジックで利用するのは今回が初めてです。}}シェーダーの修正for文の部分は二次元スレッドにするとして、それ以外の部分は一次元で回したいです。for文の前にあった変数の初期化処理を第一のカーネルとして抽出しました。carD;}次は、for文に相当する二次元スレッド部分。関数の内容ほぼそのままです。for文の後のブロック、衝突予測結果を用いて加減速と、速度に応じた移動を行うブロックです。carD;}おっと、増やした&リネームした関数をファイルの先頭でカーネルとして宣言するのも忘れずに。取得、フィールドに保持しておきます。}Updateでカーネルを呼び出す部分も修正します。コンピュートバッファーはカーネルが変わるたびにセットし直す必要があるようです。FindKernel使う意味が無くなるような決め打ちです。使って、今後のindex変動に影響がないようにしてるのに、ここで固定値使ったら片手落ちですね。冒頭に貼った画像の状態でプロファイリングしました。160〜170台で落ち着きます。多次元グループ化スレッドグループ、一次元と二次元[numthreads(64,1,1)][numthreads(8,8,1)]ご覧の通り、顕著な差は見られません。期待してたのですが残念な結果に。参考にしたサイトには「二次元配列を一つのindexで回すような計算の無駄を省ける」とか書いてあったが、逆に計算量が変わらないのならば効果はないということか。時々ピークがあるせいでしょう。ばらつきありますが、fps的に無視できるレベル。最初に参考にしたソースが[numthreads(8,1,1)]だったので、ずっとそれでやってきましたが、8というのはどうやって決めたのかふと疑問に思ったので、スレッド数を変えることでどんな効果があるのか4と128という極端なスレッド数で比較してみました。グループ内スレッド数、4スレッドと128スレッド[numthreads(4,1,1)][numthreads(128,1,1)]こちらも顕著な差は見られませんでした。最適値にチューニングする必要がないと考えれば気が楽ですね。スレッド数はデータを扱いやすい単位で好きに指定すればよさそうです。まとめ・感想パフォーマンス向上を期待して、二次元スレッド・多段カーネル化してみた。パフォーマンスに顕著な差はみられなかった。計算量が変わらない限り、スレッドの次元やカーネル数変えてもあまり意味はないようだ。一度に回すスレッド数も、全体の計算量が変わらない限り意味はなさそうだ。偏りが原因と思われる。if文を減らすべきかも。requestStockLike0@Shinoda_NaokiFollow株式会社テクロス京都を拠点にソーシャルゲームの開発・運用、その他システム開発を行っています。upLoginユーザーは見つかりませんでした。