3

この非常に役立つ投稿を見つけたので、コンパイラの最適化について明確にしたいと思います。この関数があるとしましょう (元の投稿と同じ):

template<int action>
__global__ void kernel()
{
    switch(action) {
       case 1:
       // First code
       break;

       case 2:
       // Second code
       break;
    }
}

コンパイラは、コンパイル時にテンプレート変数が不明な関数を呼び出した場合でも、到達できないコードを排除するという意味で最適化を行いますか? たとえば、2 つの別個の関数を作成するようなものですか? 例えば:

kernel<argv[1][0]>();
4

2 に答える 2

4

短い答え:いいえ。

テンプレートは純粋にコンパイル時にインスタンス化および生成されるため、コンパイル時には不明なため、argv の値を使用できません。

なぜあなたはそれを試してみてそのコードをコンパイラに投げなかったのか不思議に思います.テンプレート引数はコンパイル時の定数でなければならないと言ったでしょう.

更新: コメントで、主にパフォーマンスではなく読みやすさについて語ったので、スイッチ/ケースの使用をお勧めします:

template <char c> void kernel() {
  //...
  switch(c) { /* ... */ }
}

switch (argv[1][0]) {
  case 'a': 
    kernel<'a'>();
    break;
  case 'b': 
    kernel<'b'>();
    break;
  //...
}

決定を下さなければならない値 (つまりargv[1][0]) は実行時にしか分からないため、実行時の決定メカニズムを使用する必要があります。それらの中で、switch/case は、特に異なるケースが多すぎない (ただし 2 つ以上) 場合、および特にケース間にギャップがない場合 (つまり、「a」、「b」、「c」、 1、55、2048 の代わりに)。その後、コンパイラは非常に高速なジャンプテーブルを生成できます。

于 2013-02-28T15:00:29.853 に答える
0

テンプレートに慣れていないので、いくつかの重要な事項を勉強する必要がありました. 最後に、私は自分の問題の解決策を思いつきました。コマンド ライン引数に応じてテンプレート パラメーターを使用して関数を呼び出したい場合は、次のようにする必要があります。

if(argv[1][0] == '1')
    kernel<1><<< ... >>>();

if(argv[1][0] == '2')
    kernel<2><<< ... >>>();

また、そのようなプログラムの ptx ファイルをチェックしたところ、この場合、コンパイラが最適化を行って、switchステートメントなしで 2 つの異なるカーネル関数を生成することがわかりました。

于 2013-02-28T16:47:05.887 に答える