470 likes | 575 Views
最適化. optimization よりよいコードを得る. 最適化とは?. 実行時間を短くする *どんなコンピュータでも, 特にスーパーコンピュータなど *一部の最適化でも効果のある場合あり 所要記憶容量を小さくする *機器組込マイコンなど *プログラム全体の最適化. 最適化の努力と効果. 最適なコードとの差. 最適化の努力. 最適化の分類. 1.解析の範囲 ○大域的最適化:プログラム全体 ○局所的最適化:一部分,覗き穴最適化 2.ハードウェアとの関係 ○機械依存 ○機械独立. 基本ブロック. 条件
E N D
最適化 optimization よりよいコードを得る
最適化とは? • 実行時間を短くする *どんなコンピュータでも,特にスーパーコンピュータなど *一部の最適化でも効果のある場合あり • 所要記憶容量を小さくする *機器組込マイコンなど *プログラム全体の最適化
最適化の努力と効果 最適なコードとの差 最適化の努力
最適化の分類 1.解析の範囲 ○大域的最適化:プログラム全体 ○局所的最適化:一部分,覗き穴最適化 2.ハードウェアとの関係 ○機械依存 ○機械独立
基本ブロック • 条件 1.ラベルなし(最初の文以外) 2.ジャンプなし(最後の文以外) 3.極大(maxmal) • Idea 1.飛び込みなし 2.飛び出しなし 3.順番に処理(計算)される
基本ブロック:例 L: t = 2 * x ; w = t + x ; if (w >0) goto L ; 先頭にラベルあり w=3*x と変更可 最後にジャンプあり
制御フロー(flow)グラフ • 方向付きグラフ 1.ノードは基本ブロック 2.ノードAからノードBへの矢印(→) ノードAの最後の命令から ノードBの最初の命令へ行く可能性あり
制御フロー:例 a=3 i=1 L: a=a+4; i=i+1 if(i<5)goto L
実行速度の改善 1.命令の実行回数を減らす ループ内命令→ループ外命令 2.より速い命令を使う メモリ→レジスタ 3.並列度を上げる ベクトル化コンパイラ
★ 1. 命令の実行回数を減らす 1.1 一度実行した結果を再利用 1.2 コンパイル時にできるものはコンパイル時に実行 1.3 実行頻度の少ない場所に移す 1.4 実行回数を減らすようプログラム改造 1.5 式の性質の利用 1.6 冗長な命令を取り除く 1.7[手続き呼び出しの]特殊化
1.1 一度実行した結果を再利用 • 共通部分式の削除 (1)a=b+c; .......... (2) d=(b+c)*e; → d=a*e; • 条件 • (2)の前に必ず(1)の計算 ← フロー解析 • b,cの値に変化なし
1.2 コンパイル時にできるものはコンパイル時に実行する1.2 コンパイル時にできるものはコンパイル時に実行する • 定数の畳み込み(定数伝播) (1)a=3.5*2.0; .......... (2) b=a+16.5; → b=23.5; • 条件 • (2)の前に必ず(1)の計算 ← フロー解析 • aの値に変化なし
1.3 実行頻度の少ない場所に移す • ループ内→ループ外(命令の移動) for(i=0;i<10;i++){ a=12.3; a=12.3; for(i=0;i<10;i++){ ........... ................ } } • 条件 • aがループ不変=相対定数
1.4 実行回数を減らすようプログラム改造 • 部分冗長性の除去 if(a>b){ y=c+d; if(a>b){y=c+d; } z=x+y; } else { x=c*b; else { x=c*b; z=x+y; a=z-b; } z=x+y; a=z-b;} z=x+y; ........... • 部分冗長性:z=x+yはelseの時冗長,ifの時冗長でない
1.4 実行回数を減らすようプログラム改造 • ループ融合 for(i=0;i<10;i++){ for(i=0;i<10;i++){ a[i]=x[i]; a[i]=x[i]; } for(i=0;i<10;i++){ b[i]=x[i]+y; b[i]=x[i]+y; } } • ループ制御の命令が半分 • x[i]へのアクセスの局所性の改善
1.4 実行回数を減らすようプログラム改造 • ループ展開 for(i=0;i<10;i++){ for(i=0;i<10;i+=2){ a[i]=x[i]+y; a[i]=x[i]+y; a[i+1]=x[i+1]+y; } } • ループ制御の命令が半分 • 並列実行できる機械で特に有効
1.5 式の性質の利用 • 算術式の演算順序変更 a=x+y+z; b=x+y; b=x+y; a=b+z; • 加算演算が少なくなる • レジスタが効率よく利用できる
1.5 式の性質の利用 • 式の簡単化 a=x*1; a=x; b=y+0; b=y; • 計算の省略→計算が速い&計算が正確 計算が 不要かもしれない
1.6 冗長な命令を取り除く • 無用命令の削除 a=a; b=b+0; c=x+y; • フロー解析が必要 なし 以降のプログラムで cがつかわれていない場合
1.6 冗長な命令を取り除く • 複写の削除 (1)a=b; a=b; ......... ............. (2)c=a+d; c=b+d; • フロー解析が必要 (2)以外aを使っていなければ, 削除できる
1.7[手続き呼び出しの]特殊化 • 手続きの展開(インライン展開) • 実引数の受け渡しなどcallの処理回避 main main call 手続き 手続き
1.7[手続き呼び出しの]特殊化 • 手続きの複製 • 実引数が定数の場合:コピーできる main main call call 手続き 手続き 手続き
2. より速い命令の利用 2.1 レジスタを利用する:レジスタ割り付け 2.2 高性能な命令を利用する:ベクトル計算 2.3 プログラムの局所性を高め, メモリアクセスを速くする:キャッシュメモリの利用 2.4 より単純な命令を利用する:乗算→加算
2.1 レジスタ割り付け • 大域的 使用頻度が高いデータをレジスタに入れる • 局所的 一度レジスタに入れたデータはできるだけレジスタに置いておく • データの生存区間の解析
2.2 特殊な命令の利用 • ベクトル化 for(i=0;i<1000;i++){ a[i]=b[i]+c[i]; } ⇒VR0=b[0:999] ; VR1=c[0:999]; VR0=VR0+VR1; a[0:999]=VR0; • 例 for(i=0;i<1000;i++){ for(i=0;i<1000;i++){ a[i]=b[i]+c[i]; a[i]=b[i]+c[i]; } for(i=0;i<1000;i++){ d[i]=a[i]+e[i]; } d[i]=a[i]+e[i]; }
メモリ階層 (0)レジスタ (1)1次キャッシュ高速,小容量 (2)2次キャッシュより大容量 (3)主メモリ (4)ディスク仮想記憶 (5)他のプロセッサのメモリ アドレス空間共有 *メモリアクセスの局所性を高める 速度大
2.3 局所性:ループのタイル化 for(j=0;j<100;j++){ for(jt=0;jt<100;jt+=t){ for(k=0;k<100;k++){ for(kt=0;kt<100;kt+=t){ for(i=0;i<100;i++){ for(it=0;it<100;it+=t){ for(j=jt;j<min(jt+t-1,100);j++){ for(k=kt;k<min(kt+t-1,100);k++){ for(i=it;i<min(it+t-1,100);i++){ c(i,j)=c(i,j)+a(i,k)*b(k,j); c(i,j)=c(i,j)+a(i,k)*b(k,j); } } } } } } } } }
2.4 演算の強さの軽減 • x**2 (べき乗)⇒ x*x (乗算) • x*2 (乗算)⇒ x+x (加算) • x/5.0 (除算)⇒ x*0.2 (乗算) • a=5; x=2; for(i=0;i<100;i++){ for(i=0;i<100;i++){ x=3*i+a; x += 3; y=f(x); y=f(x); } }
3. 並列度を上げる 3.1 命令レベルでの並列実行 スーパスカラプロセッサの命令の実行順序を選ぶ(=命令スケジューリング)⇒並列度を上げる 3.2 プロセッサレベルでの並列実行 データやプロセスを並列計算機の各計算機に分散して,並列に実行する
★ 局所最適化:例 a=x**2 b=3 c=x d=c*c e=b*2 f=a+d g=e*f a=x*x e=6 f=a+a g=6*f 強さの軽減 d=a dが不要 定数 e=3*2=6 dをaと置き換える eを6と置き換える
★ システムプロジェクトⅠ(1) PUSHI 3 PUSH 4 PUSHI 5 SUB ASSGN REMOVE PUSH 4 PUSHI 5 SUB POP 3
PUSHI 13 PUSHI 4 SUB PUSHI 9 システムプロジェクトⅠ(2)
PUSHI 1 PUSHI 4 PUSHI 2 ADD ASSGN REMOVE PUSHI 6 POP 1 システムプロジェクトⅠ(3)
100 PUSHI 1 101 PUSHI 4 102 COMP 103 BGT 106 104 PUSHI 0 105 JUMP 107 106 PUSHI 1 107 100 PUSHI 0 システムプロジェクトⅠ(4)
PUSHI 1 COPY LOAD PUSH 3 ADD ASSGN REMOVE PUSH 1 PUSH 3 ADD POP 1 システムプロジェクトⅠ(5)
PUSHI 1 COPY LOAD PUSHI 1 SUB ASSGN REMOVE PUSH 1 DEC POP 1 システムプロジェクトⅠ(6)
PUSHI 1 PUSHI 0 ASSGN REMOVE PUSHI 2 PUSHI 0 ASSGN REMOVE PUSHI 1 PUSHI 2 PUSHI 0 ASSGN ASSGN REMOVE システムプロジェクトⅠ(7)a=0;b=0;→a=b=0;
★ c<b 10 PUSH 2 11 PUSH 1 12 COMP 13 BLT 16 14 PUSHI 0 15 JUMP 17 16 PUSHI 1 17
10 PUSH 2 11 PUSH 1 12 COMP 13 BLT 16 14 PUSHI 0 15 JUMP 17 16 PUSHI 1 17 BEQ 24 18 PUSHI 0 19 PUSH 0 20 PUSHI 1 21 ADD 22 ASSGN 23 REMOVE 24 10 PUSH 2 11 PUSH 1 12 COMP 13 BGE 18 14 PUSH 0 15 INC 17 POP 0 18 システムプロジェクトⅠ(8)if(c<b) a=a+1;
課題13.1 最適化の例 1.最適化しなさい. a=2 b=3 c=2*a d=2*x e=b*2 f=a+e g=e*f 2.最適化しなさい. a=1; for(i=0;i<100;i++){ y=2*i; x=a*3+2*i; }
1.システムプロジェクトⅠで if(a>b) c=a+b; を最適化しなさい. 2.システムプロジェクトⅠで while(a>b)b=b+1; を最適化しなさい. 3.最適化について述べなさい. 課題13.2 システムプロジェクト 最適化の種類
問1: 命令の実行回数が減らないのは? ① 一度実行した結果を再利用 ② コンパイル時にできるものはコンパイル時に実行 ③意味が変わらないなら, ループ内の命令をループ外に移す ④実行回数を減らすようプログラム改造 ⑤冗長な命令を加える ⑥正解なし
問2: 誤っているのは? a=x**2 b=3 c=x d=c*c e=b*2 f=a+d g=e*f ①a=x*x ②d=a ③e=6 ④f=a+a ⑤g=b*f ⑥正解なし
問3: 誤っているのは? a=x*2 b=4*3 c=x+x d=c*c e=b*2 f=a+d g=e*f ①a=x+x ②b=12 ③c=x*2 ④e=24 ⑤g=24*f ⑥正解なし
問4 PUSHI 2 PUSH 4 PUSHI 5 SUB ASSGN REMOVE PUSH 4 PUSHI 5 SUB ①POP3 ②POP 2 ③PUSH 2 ④PUSHI 2 ⑤ASSGN ⑥正解なし 問4
問5: c==b 10 PUSH 2 11 PUSH 1 12 COMP 13 14 PUSHI 0 15 JUMP 17 16 PUSHI 1 17 ①BEQ 16 ②BGT 17 ③BLT 16 ④BLT 17 ⑤BNE 16 ⑥正解なし 問5