AOBA's Information Processing Education
1997/07/26
注意1:このページは、回線を切断した後でゆっくりご覧になってください(テキストを印刷する場合は、その取り扱いに注意してください)。
注意2:背景が白地の画面を長時間見つめていると頭が痛くなってしまいますので、ここは背景をグレーにしています。
訂正:7月27日の午前10時以前にご覧になった方へ
bに関する解答群のアが誤っていました。
(誤):ア p:=x/y+y/z;
(正):ア p:=x/z+y/z;
今後はこのような事がないよう十分注意しますので、お許しのほど・・。
「昭和62年 第1種 午前 問5」 問5 最適化コンパイラに関する次の記述を読んで設問に答えよ。
プログラムを効率のよいものに変換することを最適化という。通常は実行時間の短縮を最適化の目標にすることが多い。原始(ソース)プログラムの冗長な部分を見つけ出し、実行時間の短い目的プログラムを生成するコンパイラを最適化コンパイラという。
最適化の手順の一部を挙げると次のとおりである。
- 定数同士の演算はコンパイル時に行う。
- 引数が定数である組込み関数の計算はコンパイル時に行う。
- 繰り返し現れる等価な計算式(共通式)は1回だけ計算するようにする。
- 2進法の計算機の場合、2のべき乗による整数の乗除算はシフト命令で行う。
- 四則演算における分配法則が適用できる場合は、これを利用して演算回数を減らす。この場合、括弧の除去または追加のために演算順序が元の式と異なってくる場合がある。
設問a 次のプログラムを最適化してできるプログラムはどれか。解答群の中から一つ選べ。
p:=p+q*r;
s:=p+r*q;設問b 最適化コンパイラを使ったときと、最適化なしのコンパイラを使ったときで、答の精度が異なる可能性のある文(statement)を、解答群の中から二つ選べ。ただしk,jは整数表示、p〜zは浮動小数点表示とする。
aに関する解答群
ア t:=q*r; イ t:=q*r; ウ t:=q*r; p:=p+t; p:=p+t; s:=p+t; s:=p; s:=p+t; p:=s+t; bに関する解答群
ア p:=x/z+y/z; イ q:=x+1.0+2.0; ウ r:=(x+2.0)/3.0+1.0; エ s:=(x+2.0/3.0)+1.0; オ t:=x+sin(3.141593/2.0); カ k:=32*j;
解説 設問a
解答群のすべてのプログラムは、最適化の手順3項を適用してq*r(r*q)を先に計算し、それをtと置いたものです。
アについて
元のプログラムではpとsは明らかに異なる値を取りますが、アのプログラムはpとsが同じ値となってしまいます。したがってこれは誤りです。ウについて
ウのプログラムは元のプログラムとpとsの値が逆になってしまいますので、これも誤りです。設問b
この設問で注意してほしいのは、誤差が生じるものを選ぶのではなく、「元のプログラムと演算結果が異なる可能性のあるものを選ぶ」ことです。
仮に、x=1.0、y=2.0、z=3.0、浮動小数点の有効桁を小数点以下6桁として考えてみましょう。アについて
元のプログラムの演算結果=(1.0/3.0)+(2.0/3.0)
=0.333333+0.666666
=0.999999アのプログラムに最適化の手順5項を適用すると、p:=(x+y)/z;と等価な式に変形されますので、演算結果は以下の通りとなります。
アのプログラムの演算結果=(1.0+2.0)/3.0=1.0
元のプログラムの誤差は「丸め誤差」といい、ある数値を有効桁の範囲で表現するときに発生するものです。
その他の浮動小数点の誤差としては、絶対値が大きく異なる値どうしの加減算を行った時に発生する「情報落ち」と、逆に絶対値が非常に近い値どうしの加減算を行ったときに発生する「桁落ち」(有効桁数が減少するもの)があります。イについて
イのプログラムに最適化の手順1項を適用すると、q:=x+3.0;と等価な式となります。ただし、元のプログラムのように、実行時に1.0+2.0を計算した場合でもその部分は常に3.0です。
したがって、xの値に関係なく、イのプログラムは最適化後のプログラムと演算結果が常に同じです(解説の例の場合は常に4.0となりますよね)。ウについて
元のプログラムの演算結果=(1.0+2.0)/3.0+1.0
=2.0ウのプログラムに最適化の手順1項と5項を適用すると、r:=x/3.0+1.666666;と等価な式に変形されますので、演算結果は以下の通りとなります。
ウのプログラムの演算結果=(1.0/3.0)+1.666666
=0.333333+1.666666
=1.999999アと同じく、演算結果が異なりました。
エについて
元のプログラムの演算結果=(1.0+2.0/3.0)+1.0
=1.0+0.666666+1.0
=2.666666エのプログラムに最適化の手順1項と5項を適用すると、s:=x+1.666666;と等価な式に変形されますが、演算結果は元のプログラムと同じです。
エのプログラムの演算結果=1.0+1.666666
=2.666666xの値に関係なく、エのプログラムは最適化後のプログラムと演算結果が同じになりますよね。
オについて
イと同じように考えます。
オのプログラムに最適化手順の1項と2項を適用すると、t:=x+定数;と等価な式になりますが(定数はsin1.570796の値)、定数の部分は実行時に計算しても、コンパイル時に計算しても、同じ値となるはずです。
したがって、xの値に関係なく、オのプログラムは最適化後のプログラムと演算結果が常に同じです。カについて
カのプログラムに最適化手順の4項を適用すると、k:=j<<5;と等価な式になります(jを5ビット左シフト)。
もし、元のプログラムのように32倍した結果で桁あふれが生じたら、最適化後のプログラムでも間違いなく桁あふれが生じます。また、逆でも同じことがいえます。
したがって、jの値に関係なく、カのプログラムは最適化後のプログラムと演算結果が常に同じです。
解答
設問a イ 設問b ア、ウ