コンパイラ

上のループを、SIMD命令を使ってベクトル化しにくい主な理由はどれか。

for (i = 1; i < n; i++)
    a[i] = a[i - 1] + b[i];
  1. A直前の繰り返しの結果a[i-1]が必要で、同時に計算できないから
  2. B配列の要素の型が整数なので、SIMD命令では計算できないから
  3. Cループの回数nがコンパイル時に分からないと、ベクトル化は一切できないから
答えと解説を見る

正解:A. 直前の繰り返しの結果a[i-1]が必要で、同時に計算できないから

ベクトル化では、例えば4つの要素の計算を1つのSIMD命令で同時に行います。このループでは a[i] を求めるのに1つ前の a[i-1] の結果が必要なので、a[1]〜a[4] を同時には計算できません。このような繰り返しをまたぐ依存(ループ運搬依存)があると、そのままではベクトル化できません。整数もSIMDで計算でき、回数が実行時に決まる場合も、余りの部分を別に処理することでベクトル化できます。

  • A. 正しい。直前の結果に依存するため、同時に計算できません。
  • B. 整数の計算もSIMD命令で行えます。
  • C. 回数が実行時に決まっても、余りを別に処理すればベクトル化できます。
この分野を解く 分野ページへ

コンパイラのほかの問題

  1. 上の関数で、コンパイラが *b の読み込みをループの外に出す最適化を、そのままでは行えない理由はどれか。
  2. コンパイラのレジスタ割り当てで、干渉グラフを塗り分ける(彩色する)方法を使うとき、グラフの節と辺が表すものの組み合わせとして正しいものはどれか。
  3. レジスタ割り当てで「スピル」が起こると、生成されるコードはどうなるか。
  4. コンパイラの命令スケジューリングの主な目的はどれか。
  5. 上の関数の最後の再帰呼び出しに末尾呼び出しの最適化を行うと、どのような効果があるか。