最適化 - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年9月号
180件見つかりました。

1. 月刊 C MAGAZINE 1990年9月号

特・集コーイラ してもよいのか ? 」という疑問に対する解答 movcl, 8 ; 6 バイト長て、 44 クロック をえる一助になる。さらにコードの最適化 shl y, 80286 は革命的なものて、はなく , 漸進的な向上を shl y, 8 提供するものとして分類することにもなる。 ; 5 バイト長て、 8 クロック このレビューは , コンパイラが一般的な このクラスの最適化は改良余地部分を小さ なコードシーケンスにかぎっているため , 方法により , サイズまたはコードの最適化 ー連の最適化テスド ヒ。ープホール ( のぞき穴 ) 最適化とも呼ばれ 能力の解析を目的としている。各低レベル テストは , 指定の最適化をテストするため る。そのほかには 8088 , 80286 , 80386 など のインストラクションタイミングや外部デ に設計したコードを含んて、いる。各テスト コンパイラの最適化能力テストは本当に をコンパイルしオプジェクトコードを検査 ータバスサイズの違いを考慮し , コードサ 困難て、あり , しばしばフラストレーション イズまたは実行時間が最高になるようにコ し , 最適化されたかどうかを割り出す。も の元凶となる。なぜなら , 注意深く作成さ ード生成を調節する最適化が考えられる。 し最適化されていたら効果の程度をコンパ れたコードが簡単に捨てられてしまうから 最適化の余地は極めて大きく , 単純なも イラ間て、比較する。このように人工的な環 だ。最適化とその結果の測定の間には確か 境て、あり , しかもテストの範囲がかぎられ のからインプリメントが困難なものまて、い な相互関係があるのて、 , フラストレーショ ろいろある。 386 や DOS 工クステンダなどの ている以上 , この初期結果を問題に対する ンは二者の関係を測る重要なものさしにな 最終結果て、あると盲目的に考えないて、ほし 最新技術によって , これまての想定は役に る。またコンパイラの一部には , 条件しだ 立たなくなり , まったく異なった視点が求 いて、 , ある種の最適化を認識するものもあ い 加えて , 大型アプリケーションの作成に められ , 事態はさらに複雑化する。しかも るため , 結果が完全だとは断言て、きない も各コンパイラを使用した。このアプリケ それは , コンパイラだけにとどまらない このテストケースはわかりやすいものから ーションは 25 のソースモジュールから構成 TopSpeed と Microsoft リンカて、はさらに時 開始し , 徐々に困難なものへと発展させた。 され , ランタイムライプラリとオペレーテ 間とスペースの最適化が可能だ ( Table 1 ) 。 単純なケースを満足に最適化て、きなければ , コラム 1 「 386 / 486 コード生成と最適化リン イングシステムをかなり使用している。現 そのコンパイラ能力の限界を示す十分な証 力」て、は 386 と最適化リンカに焦点をあて 実のアプリケーションを検査することて、 , 「コ 拠となる。 ンパイラ X を使ってアプリケーションを出荷 また , ほとんどのテストには主観的な解 、 0 結果の計測ーー Lattice C XX XX Aztec C XX High C Zortech C X ( 注 2 ) Turbo C XX XX TopSpeed C XX XX XX Microsoft C XXX XX Ecosoft C Watcom C X ( 注 1 ) X X XXX XXX XX XX XXX XX XXX XXX XXX XX XX X ( 注 3 ) XX XX XX XX( 注 4) XX XX 1 4 2 5 ( 注 1 ) Watcom C は変数か含まれていると定数式をフォールドしない ( 注 3 ) TopSpeed C は無用な場所に条件 NOP を差し込む 7 1 1 6 1 6 ( 注 2 ) Zortech C は多忙式を認識するが全バスからのコードをホストしない ( 注 4 ) Watcom C はバイトテータをバックしないのでムダな空間を生ずる 特集米国コンバイラ事情 41

2. 月刊 C MAGAZINE 1990年9月号

特・集コイラ つのアプリケーションを 7 つのコンパイラて、 (TabIe 5 「パフォーマンス早見表」て、行っ チマークを盲信したとしても結果を報告す 実行するのは骨が折れるが , 努力のかいあ たような ) の合成べンチマークなら実行す る価値がある。 sieve of Eratosthenes て、は る結果の期待て、きる作業て、はある。 るのは楽だが , 結果をねじ曲げてしまう危 Microsoft が Lattice を上回り , Watcom がわ sieve Of Eratosthenes や Dhrystone べン 険が伴う。 ANSI C をガイドとしても , ひと ずかの差て、 3 位につけた。これ以上詳細な結 されることはない。スマートリンクとは死 んだ関数の削除以外のなにものでもない。 関数ひとつひとつを別のソースモジュー ルで定義すればよいと思うかもしれないが , モードでははるかに貴重な改善をもたらす 時問と空間の最適化は , 必すしも . OBJ フ それでは問題の包み直しにすぎない。ソー (Table E)O ァイルを書くことだけでは終わらない。コ スモジュール数はあっという間に増加し , セグメントレジスタのリロードをプロテ ンバイラは , ひとつのソースモジュール内 MS-C 5 コのランタイムライプラリでは 400 本 の未参照のスタティック関数の最適化 , 削 クトモードで行うたびに , 複雑なマイクロ を超えるソースファイルになってしまう。 除が可能だが , グローバルスコープをもっ コードシーケンスが起動され , 新しいディ コードとデータの共用が困難になり , 効率 スクリプタをロードし有効化する。コード た関数がそれ以降に参照されるかどうかは は悪化し , 大幅なメンテナンス問題を引き を同じセグメントに置いて near コールを わからない。コンバイラは過去のコンバイ 起こす。このような問題は , コードとデー 使えば高価なオーバヘッドを避けられる。 ルとは関係なく , 一度にひとつのモジュー タの定義が自然なインテリジェントリンカ しかしコードセグメントをバックしただけ ルをスキャンするので , 80X86 セグメントア が生成する , 最小サイズのロードモジュー では問題の半分しか解決しない。後続の fa 「 ーキテクチャの特性によるワーストケース ルが可能なスマートリンクによって避けら リターンは最適化されておらず , まだオー を想定せざるえない。 る。 J 曰社によれば , TopSpeed では 20 以下の バヘッドが残る。プロテクトモードアプリ 最初の MS-DOS リンカによる最適化は , MS ソースモジュールですんでいるそうである。 ケーションの設計ではこの点を考慮すべき Microsoft でのインプリメントとは比較になら -C 5.1 付属のリンカで最初に収録され , 現 在の Lattice リンカにも見られる fa 「コールの だ。 ない改善である。 スマートリンクの時期は到来したが , ま 変換である。 fa 「コールの変換とは fa 「コール C では TopSpeed C だけがスマートリンクを だ一般化にはいたっていない。 リンカのコ を相当する高速かっ同等な nea 「コールで置 実現している。しかし , Turbo Pascal や Top ンセプトは , あるモジュールでの外部参照 き換えることだ。 speed Mod a ー 2 ではスマートリンクが実現 とほかのモジュールの定義を突き合わせる 最適化前 最適化後 されてから久しい。コードサイズの点では だけだ。そうすることで MS-DOS リンカは実 スマートリンクは重要だが , これが一般的 call fa 「 p 「 OC_X nop 行ファイルのコンポーネントとしてオプジ になるかどうかは疑わしい。なぜなら時間 push cs ェクトモジュール全部を取り込むわけだ の最適化が注目されているからだ。実行時 call near proc X これはなんの論争も起こさない。 通常この最適化はひとつのモジュール内 問に向けられる関心がスペースの最適化へ 外部参照を満たすことに無関係な関数を含 向けられるまでは , スマートリンクは標準 の関数コールで見られ , コードジェネレー んだモジュール内の全関数までを取り込む タによって行われる。リンカの /PACKMODE 的なリンカの最適化とはならないだろう。 のは別問題だ。未参照関数は決してコール オプションによって , モジュール間での最 適化がオンになる。ー連のコードセグメン TabIe E トをひとつのグループにまとめるのがバッ キングである。実質的に複数セグメントを ひとつの共用セグメントに分解することに なる。コードセグメントをバックすると , リアルモードでは fa 「コールよりクロック数 をいくつか削減するだけだが , プロテクト 最適化リンカ プロテクトモード 286 386 リアルモード 386 286 「 / っム冖 0 CALL fa 「 CALL nea 「 削減クロック数 ( 0 CO っ t) っ乙 4 ー 3 3 0 4 2 っ 4 一 1 ーっ 4 特集米国コンバイラ事情 47

3. 月刊 C MAGAZINE 1990年9月号

TabIe 1 リンカによる最適化 Aztec C Ecosoft C High C Lattice C Mic 「 osoft C TopSpeed C Turbo C Watcom C Zortech C スマートリンク Fa 「コール変換 Fa 「コール変換は Mic 「 osoft または Latt ℃ e に付属のリンカを使えばほかのコンパイラでも使用可能 ( 広域 ) 」と「最適化」というホットな形容 詞が現在の C コンパイラ事情を表している。 最適化コンパイラは例外というより当然と なっており , どのコード最適化をコンパイ ラがサポートしているかを見極めることに 意義がある。さらに重要なのは , 最適化が プログラムに及ばす影響を計測することだ。 世界レベルのアプリケーションを作成する 際には , その挑戦の半分は最適て、ないもの を発見することにある。 コンヒ。ュータブログラムは時間とスペー スの 2 次元世界に生息している。定義上の最 適化とは , コードのトランスフォーメーシ ョン以外のなにものて、もなく , 通常は ( 必ず しもそうて、はないが ) 最適化されていないも とのコードに対して改善されている。もち ろん時間とスペースを同時に短縮する最適 化がベストだが , この両者は本質的に相容 れない このレビューて、は , 4 つのクラスのコード 最適化をチェックする。アルゴリズム , ソ ース , 中間形式 , ターゲットに区分けし , 各コンパイラがどの程度の最適化を行うか を検証する。アルゴリズムの最適化はコン パイラとは無関係て、あり , キーポードに触 れるはるか以前に頭の中て、行われるべきこ とて、ある。ほとんどのコンヒ。ュータソフト ウェア同様 , 最局の最適化コンパイラさえ ご存じのガーベージイン , ガーベージアウ ト ( ごみが入ればごみが出る ) の原理にした がっている。厳密にいえば出力の質は入力 40 CMAGAZINE 19 囲 9 適化コンパイラは十分にうまく書いたコー こそ最重要視すべきだ。なぜなら良質の最 これを念頭におけば , ベストな設計判断 データ関数の質て、ある。 ドに対して 5 % から 15 % 程度の向上をもたら すが , 良質なアルゴリズムによっては数倍 の向上につながるからだ アルゴリズムの最適化を除くとソース , 中間形式 , ターゲットの最適化がコンパイ ラの認識するところとになる。最適化がソ ースに割り付けられるのは , マシンのアー キテクチャに依存することなく , 最適化が 上手に設計されたコンパイラ ( または十分に 知識が豊富な人間の手 ) によって可能な場合 だ。このような最適化て、はソースコードの 読みやすさと保守のしやすさは向上する。 ただし , 式や文の追加が必要になる。 定数の折り返し (constant folding) の例を 見よう。 #define dim(x) (sizeof(x)/sizeof(xC0])) 配列境界をつねに覚えておかなくてもこ のマクロ中のふたつの定数は , マクロを使 用した時点て、相当する定数て、置き換え可能 だ。そのほかのソースの最適化にはループ のアンローリング , インラインコード展開 , コードホイスティングなどがある。 コンノヾイラによってはソースコードが中 間形式に変換されてからまったく新種の最 適化が適応される。中間最適化はひとつの シーケンスプロック ( ローカル ) 内と , 複数 プロックにわたるグローバルスコープをも ったものに大別される。ローカルな最適化 は MS-C 5.1 や WatcomC 6.5 などの PC コ ンパイラの時代から存在し , 共通部分式 , コヒ。ー伝達 , 死変数の最適化に分かれる。 今年の新規な最適化において重要なのは Lattice, Microsoft, Zortech などて、のグロ ーバル最適化コンパイラて、ある。グローバ ル最適化コンパイラは改善の余地のあるコ ードを丹念に かっ細部にわたって探求す るが , 余地の拡大によってコンパイラ自体 の仕事は極端に複雑化し , 処理時間が増大 する。 コードジェネレータによる最終最適化は ターゲットプロセッサの特性 , すなわちこ の場合インテル 80 x 86 のセグメントアーキ テクチャをうまく利用する。たとえばター ゲットプロセッサが 80286 て、あるとの指定が あれば , すべてのコンパイラは多少なりと も良質なコードの生成が可能だ。複数ビッ トシフトを行う以下の文を考えてみよう。 y くく 8 ; X アセンプリ言語に変換された以下のコー ドインストラクションセットにはかなりの 違いが見られる。 8086 / 88 TabIe 2 テストした最適化 定数フォールティング コードホイスティング インライン関数 内部関数 共通部分式削除 帰納変数削除 工イリアス最適化 多重文字列のマージ テールマージ 強さの削減 インストラクションアライメント テータアラインメント レジスタバラメータ コード生成 計

4. 月刊 C MAGAZINE 1990年9月号

特・集コーイラ 果のレポートをあえてしないのは , わすか 9 行のコードを最適化する能力と , 300 から 300 , 000 行のコードを使ったプロジェクトと は何の関係もないと考えたからだ。べンチ マークを進めていくと Dhrystone が sieve of Eratosthenes より , よい結果となった ( 現実 のアプリケーション結果に近づいた ) 。 Wat- com と Microsoft のデッドヒートになり Top- Speed がこれにつづいて 3 位となった 合成べンチマークについてはもう十分だ ろう。 Table 6 は compact と large 各モデル の組み込みシステム用のツールを作成した テスト結果て、ある。商用製品て、あることに 加えて , このアプリケーションのコードサ イズが compact モデルの 64K ノヾイトのリミッ トに近づいている点に興味がある。すべて のコンパイラが , large モデルて、は成功した のて、 large を結果のサマリーに使用した。 Watcom が最小かっ最速コードを生成し , わずかの差て、 Microsoft と Zortech がつづい た。すべてのコンパイラが好結果を出して トップと最下位との差は 21 % だ。 おり , コンパイラ間の差は興味深い。プログラ ムを詳細に解析するとアプリケーションて、 2 / 3 の時間を , 残りの時間をファイルのリー ドライトに消費している。この状況下て、は ラインタイムライプラリ , ダイナミックメモリ管理ルーチンのインプ リメントが順位を決定づけている。 Table 6 実物のプログラムの作成 Turbo C が 4 位に終わっている。タイミン グ解析をすると ,malloc( ) に TurboC は 270 ミリ秒 , Watcom C て、は 50 ミリ秒を要して おり , 差の大部分を占めている。 Microsoft と Watcom が高速なアロケーションを指向し ているのに対し , BorIand のアプローチは実 行時間を犠牲にしてもヒープの細切れを防 止している。省メモリアプリケーションて、 はこれはすばらしいことだが , 時間計測を しているかぎり不利になるというわけだ。 残念ながら BorIand の節約にはポイントを与 えられない しかし , これは別のところて、効力を発揮 する。 qsort( ) の実行時間て、は , BorIand(91 ミリ秒 ) は Watcom(190 ミリ秒 ) より 2 倍 , Mi crosoft(258 ミリ秒 ) に対しては約 3 倍近く速 くなっている。コンノヾイラベンダの暗黙の 設計判断が , アプリケーションに直接イン パクトを与えたポイントだ。それぞれの状 況に応じてユーザがランタイムライプラリ のアルゴリズムがどう設計されているかを 判断しなければならないことになる。これ て、は買い手が危険を負担することになる。 評価に対する判断 トップと最下位の差が開く。待ちに待った チェックが質量ともに大きくなるに従い MS-C 6.0 コンパイラが最高の最適化コンパ イラて、ある。 Lattice と TopSpeed と Wat com, この 3 者が Microsoft に並ぶにはアッ プデートが必要だ。さらなる飛躍をもって レドモンド ( 訳注 : シアトル東部の Microsoft 社の所在地 ) の挑戦に各コンパイラメーカー が応じることを期待したい コンパイル時間については Turbo C がリ ーダーだ。楽勝て、ある。次いて、 MetaWare と Zortech コンパイラが良好な成績をおさ め , そのほかのコンパイラと同様にランク される。この両者は 386 と C 十十環境て、はラ イバルたちを凌駕している。 C マーケット初 登場の JPI はとくに注目に値する 0TopSpeed はユニークな特長をもったすばらしい最適 化コンパイラて、あるが , 荒削りなところに 成熟不足が見え隠れする。 Aztec と Ecosoft はそのほかのコンパイラと競争するだけの 力をもち合わせていない。それなりの長所は あるのだが (Ecosoft の lint は目を見開かせて くれる ) , 互換性のなさが機能を制限して る。 パフォーマンスを基礎にしてコンパイラ を選択すると , 「木を見て森を見す」のごと くになりかねない。だがしかし , ひとっし かコンパイラを所有て、きないなんて誰がい うのだろうか ? コードサイズ (compact モテル ) コードサイズ ()a 「 ge モテル ) 作成時間 ( 秒 ) 実行時間 (compact モテル ) 実行時間 ()a 「 ge モテル ) パフォーマンス比 ()a 「 ge モテル ) High C 十 86K 十 3.694 Lattice C 68K 7 1 K 640 3.294 3.553 M ℃「 osoft C 58K 60K 425 2.894 2.965 1 .01 TopSpeed C 十 70K 235 十 3.470 Tu 「 bo C 59K 62K 92 3.152 3.248 Watcom C 54K 55K 468 2.91 5 2.936 1 . OO Zortech C 60K 6 3 K 281 2.992 3.036 1 .03 ( 注 ) 十は compact モデルてのコードサイズか 64K を超えたためにテスト不可 全テストを ! / O に日 AM ティスクを使った De Ⅱ 310 ( 20MHz 386 ) で行った * は大型モジュールのコンバイルにティスクキャッシュをティスエープルしたので時間計測不可 特集米国コンバイラ事情 49

5. 月刊 C MAGAZINE 1990年9月号

1990 年 9 月 1 日発行 ( 毎月 1 回 1 日発行 ) 第 2 巻第 9 号通巻 12 号 1990 年 2 月 2 日第 3 種郵便物認可 提携・米国。 L G E 。誌 / 監修・石田晴久 C マカシン すへての C 言語プロクラマのための技術情報誌 SEP. 198 VOI. 2 NO. 9 980Y 。。 定価 SOFT 日 K 新連載・プロクラミンク添削 C MAGA セミナ—J レーム ソフトバンク 特集 米国 C コンラ事肩 I ・プロローグⅡ・ ANS 圓準拠度チェッグⅢ・最適化チェック Ⅳ・ライフラリチェッグ V ・ MS - C 6.0 をみる 超高速グラフィックライプラリ 2 改良・最適化 提携記事・ Sp ⅱ t Buffers, Patched Links, and HaIf-Transpositions C 言語入門講座・ポインタと構造体のまとめ レゴリズムとテータ構造入門循環・双方向・多重 最新 GNU 移植レポートⅡ ・ GNU MAKE (PC-9801) ・ GCC(FM-TOWNS) 0

6. 月刊 C MAGAZINE 1990年9月号

マ自身なのだ。新しいマシンやオペレーテ イングシステムに対する学習曲線は , プラ ットフォームの奇妙な癖や強みに矮小化さ れている。 性能および最適化 これまて、一貫して , 効率のよさが C の強み て、あった。最適化は , 技て、はなく , アート て、あり , それほど科学的なことて、はない すぐれたアセンプリ言語のプログラマは , 調子のよい日には , 最適化されたコンパイ ラよりもよい成績をあげ , 最適化されたコ ンパイラは平均的なアセンプリ言語のプロ グラマよりもよい成績を上げるというのは 事実だが , 最適化されたコンパイラには調 子の悪い日はない。しかし , 不正確な最適 化は , 最適化を行わないよりもはるかに始 末が悪いのて、 , 本格的な開発者は , 彼らの コンパイラが実際どれくらい賢いかを知る 必要があるのだ。 べンダライプラリ ライプラリの質は , アプリケーションの 性能におけるもっとも重要な要素て、ある場 合が多い。プログラムが大きいほど , 手作 業て、コード化されたアセンプリルーチンの スピードに依存する可能性が大きくなる。 ほとんどのプログラマはコンパ おそらく , イラの最適化能力における , 取るに足りな い違いを心配すべきて、はない。むしろ彼ら は , 1000 回ぐらいは呼び出すことになるラ イプラリルーチンの性能について心配すべ きて、あろう。 提供されるライプラリの範囲は価格 / 性能 比率における重要な要素て、ある。 私たちは北米における 4 つの評論者グルー プの協力を得た。各グループはすべての製 品のコヒ。ーを受け取り , これらの主要な側 面のひとつを詳細に検討した ( もっともすべ ての評論者はすべての側面に関しコメント 26 CMAGAZINE 19 9 を行うよう要請された ) 。評論者はすべての 製品を検討対象にしたわけて、はない えば , リック・ナローはインタブリタの検 討を行っておらず , テイム・パーカーはコ マンドライン専門のコンパイラの開発環境 を批評してはいない 論評は 1 か月におよぶ業界のスナップ写真 だ。比較論評て、は , 論評された製品のひと つ以上が段階的または大幅な改定を通して アップグレードされたようだ。絶えず新製 品が登場しつつあるが ( コラム「 1990 十十」参 照 ) , 非常に動きの激しい私たちの業界て、 は , 出荷中のソフトウェアだけを検討する という方針を打ち立てることが賢明だ。 とはいえ , 本特集て、は , 私たちは Microsoft の CVer. 6.0 を検討する。私たちの検討は 「第 1 回リリースの候補」て、あるべータ版に基 づいている。私たちはこの製品が非常に意 義深いものて、あると考えている。これが業 界のリーダーによる数年ぶりの主要な改訂 て、あるからだけて、はなく , 開発ツールの設 計に関する Micr 。 soft の考えを根本的に変更 するための彼らの確固たる取り組みを示し ているからだ。 C の全体像を見渡す Microsoft の大物 ,CVer. 6.0 リリースか ら驚くほど低価格な PowerC , Novell の 32 ビットのネットワークコンノヾイラから Aztec の ROM 化対応コンパイラと , C コンパイラ の選択が現在ほど容易なことはかってなか った。さらに初の DOS 向け C 十十ネイテイプ コードコンパイラて、ある ZortechC 十十が加 わる。これは C プログラマにとってオプジェ クトについて学ぶ最善の方法て、ある。 て、検討されたツールのすべては , ひとつ以 上の分野において確固たる足場を築いてい る。 lntel のチップて、大きなアプリケーション を作る場合 , ふたつのオプションがある。 数種類のコンパイラが OS / 2 をサポートして いるが , OS / 2 は必ず普及するだろう。もう ひとつのオプションは DOS に固執し , ハー ドウェアの仮説を立てることだ。 640K バイトの障害はプログラミングにお けるべルリンの壁て、ある。 80386 チップの圧 倒的な人気により , 開発者たちは拡張 DOS の受容が高まっていることを知っている ( ス コット・ラッド「 MS-DOS を拡張する 4 つの 製品」 ( ITCOMPUTER LANGUAGE 』誌 1989 年 11 月号 ) を参照 ) 。コンパイラのべン ダはこの市場に取り組んて、おり , 本特集て、 検討されたコンパイラのなかて、 , すて、に 3 っ が 80386 の強みを利用する方向に向けられて MetaWare や NoveII, Watcom の各社は 非常に大規模なプロジェクトを扱う能力を もつ咼性能製品を抱えている。もうひとつ のべンダ Microway は , たんに 80386 や DOS 工クステンダのみならず , ードウェアマ スコプロセッサを必要とする製品を打ち出 している。 私たちの論評者のすべてがこうした要件 に応じられたわけて、はないのて、 , 「 COM PUTER LANGUAGE 』誌は近いうちに NDP C ー 386 の個別検討を行う予定だ。 C を称賛するのか。 いや , 埋めてしまおう 冒頭て、述べたように , 現在 C は絶項期にあ る。したがって , それは終焉のはじまりて、 もあるのだ。 C は現在のような人気のある言 語にはならなかったはずのものだ。それは すぐれた言語て、あり , おそらく偉大な言語 て、さえあるのだろうが , 私ほど暴走するポ インタのクラッシュを享受したものはほか にいないはずだ ( 私はこうした楽しみを「ほ かの者が生きられるよう私のオペレーティ ングシステムを死滅させてくれ」といった原 型的な宗教的かっ神話的なモチーフに辿っ てみたいという誘惑にかられている ) 。しか

7. 月刊 C MAGAZINE 1990年9月号

特・集コイラ mov dx, di mov cx, 0ffffH XO 「 ax, ax repne scasb dec di lodsw 0 「 al, stosw 0 「 ah, ah loopne L3 jmp L5 stosb L5 mov ax, dx るかに良質なインプリメントになっている。 MS ー C て、はパイプラインプレークを避け , は う意味をほとんど失ってしまうことだろう。 フローが破壊され , インラインコードを使 件プランチを使ったがためにパイプライン TopSpeed インプリメントの問題点は , 条 repe movsb adC CX, CX 「 epne movsw shr cx, 1 mov CX, bX dec di 「 epne scasb mov cs, 0ffffH xchg di, si mov bX, CX sub di, cx not CX 「 epne scasb mov cx, 0ffffH mov si, offset buf mov di, bx mov bx, s2 strcat(buf, s2) mmov SI, push ds POP es N=2 N=4 N = 7 帰納変数の削除 コンパイラによっては , ループ変数を別 の変数て、の置き換えが可能て、ある。以下の コードを考えてみよう。ループから X を削除 し , その代わりに配列の開始と終了条件の 決定にループレンジを使う。非最適化版 ( ポ インタとインデックス両方を維持している ) と比較してみよう。 for(x = 0 ; x く 10 : x 十十 ) arrayCx] dummy( ) ; Zortech C ( 最適化 ) LI mov si, offset L5 call dummy mov csi], ax add si, 0002H cmp si, Offset L6 Lattice C ( 非最適化 ) a 十 5 ) は配列のインデックス たとえば a の計算をポインタに置き換え , レジスタを ループインデックスの追跡から開放するの が有用て、ある。 ループアンローリング Fortran コンパイラて、は当然のように行わ れていながら , レビューしたどの C コンパイ ラて、も行われていない最適化のひとつにル ープアンローリング ( 訳注 : ループの展 開。ループ内の実行コードを必要な回数だ け繰り返し記述する。当然コードサイズは 展開の回数分だけ増加する。以下の例て、は , 1 回しか展開していないのて、少しわかりに くい ) がある。ループアンローリングはい ずれインプリメントされるて、あろう。パフ ォーマンスに対する影響の検証は十分に時 間と労力を注ぐに値する。同時に sieve of Eratosthenes べンチマークを引き出す格好 の理由にもなる。なぜなら , インナールー プ ( 訳注 : 自分自身の内部にループをもたな いループ ) はアンローリングの最適候補だか LI XO 「 SI, 引 mov di, Offset L5 call dummy mov [di], ax lnc 引 add di, 0002H cmp si, 000aH fO 「 (k k く = FALSE ; flagsCk] 引 Z E ・ 帰納変数 ( 訳注 : induction varible ルー プ中にあって自分自身て定義可能な変数。 Table 3 ループのアンロール 以下の例は , 1 度だけアンローリングを行 った上記と同様のコードてある。たんにア ンロールした部分を希望の回数だけ繰り返 すだけて、実行バイプラインを最高度に使用 することになるのてパフォーマンスが向上 % チェンジ バージョン オリジナル 時間 ( ミリ秒 ) 30.023 30.622 27.397 26.522 25.477 26.91 1 特集 O.OO ー 1 .96 9.58 13.20 17.84 1 1 .56 米国コンバイラ事情 45

8. 月刊 C MAGAZINE 1990年9月号

「最適化チェック」 コン′イラ 特・集 より速く , より小さなコードを求めて リック・ナロー / 野口修男訳 くない驚きもある。最適化とパフォーマン ないことが多い コードジェネレータに関しても同じこと スはェモーショナルな問題て、あり , プログ がいえるが , 各コンノヾイラに付属のツール , ラマによっては妥協て、きない議論になって いる。誰しも自分なりの意見があり , 反対 ライプラリおよびプログラミング環境につ いては当てはまらない。ソフトウェア開発 意見に対して直感的に疑いを抱いてしまう。 昨年の「 C 特集」から久しい (C L 誌 1989 プロジェクトのデバッグ , 特長づけと管理 こに取り上げた最新コンパイラ群がこの 年 2 月号 ) 。そろそろ見直しの時期にさしか 厄介な問題に対して , いくらかても光を当 のよいツール要求を満たすべく , コンパイ かっている。昨年の C を取り巻く情勢は , ラベンダーは躍起になっている。他社製品 てることになれば幸いて、ある。 Microsoft や Lattice などの中心的べンダーが との差別化を図っているだけかもしれない 解析範囲をこのレビューのように絞った コンパイラのアップデートを行っていた 場合には , 勝者が誰かをはっきりと宣言す が , 全体を見ることによってコンパイラの 方て、 , BorIand はデバッガのツールセットと コード生成機能の重要度が低下し , パッケ ることなどは不可能て , べンチマークだけ TurboC の新バーションのリリースに懸命 ージ全体としての価値を重要視することに てコンパイラを選ぶのは大きな危険を伴う。 になっていた ( 訳注 : 翻訳時点て、はすて、に なる。全体像を見れば , ソフトウェア開発 コンパイラの全体像を見られなくなってし Turbo C 十十として出荷中 ) 。ワークステー 計画に重要なツールが何かをインテリジェ まうからだ。 ' こて、レビューしたトップク ションとメインフレームからの比較的新し ラスのコンパイラは , 最適化に関しては同 ントに決定て、きる。 い参入組 (MetaWare と Watcom) とヤングス 様の機能をもつ。これらのコンパイラ間て , タ—(JPI と Zortech) が DOS, Windows, お あるコンパイラがつねにほかの挑戦者を 30 % よび OS / 2 環境用の C または C 十十を販売し挑 以上も上回るようなことは , 合成的なべン 戦を開始した。 チマークを除いてはありえない。実世界て これだけ多くのコンパイラがあると , な , こ数年て広まったファッショナプルな はスルーブットに影響を与えるほかの要件 かにはどうしても驚かされるものがある。 オプジェクト指向方法と同様 , 「グローバル が多くあり , プログラマにはどうしようも もちろん , 嬉しい驚きもあればあまり嬉し 特集米国コンバイラ事情 39 はじめに 実践前の理論

9. 月刊 C MAGAZINE 1990年9月号

析を加味した。最適化の質がコンパイラご とに統一されていないためだ。 Table 2 て、は 最適化がされていればポイントを与えたが , 抜きん出た最適化を行った一部のコンパイ ラには意図的に加点した 0Microsoft の高得 Watcom C mov ax, sub ax, mov CX, ループ化したときだ。 0039H mov y, ax add ax, cx sub cx, 0030H Turbo C add ax, add ax, mov ax, mov _y, else else 最適化後 X Y 1 1 占がその好例だ て指摘する。 この点は比較結果によっ 0ff97H スペースの関係て、詳細な最適化チェック がて、きない。スルーブットまたはコーディ ングスタイルにもっとも影響のあるものだ けに限定した。 Table 2 はコンパイラがサポ ートする最適化の完全リストて、ある。 定数フォールティング 定数フォールディング (constant folding) とは , コンパイラが複数の定数を含む式を ひとつの値へ削減する処理て、ある。単純な 式はすべてのコンパイラて、ごく普通にフォ ールドされるが , 複雑な式になるとコンパ イラによっては最適化て、きないことがある。 以下に挙げた実例て、は固定フィールドと 可変フィールドのふたつを含んだレコード サイズを計算している。読みやすくするた めに計算項目をレコードフィールドの順番 どおりに配置する。普通は定数 4 を計算ずみ のレングスに加算すればすむのだが , Watcom C と Turbo C のインプリメントを比較してみ Z sizeof(BYTE) 十 sizeof(WORD) 十 y 十 sizeof(BYTE) ; Watcom C mov ax, om3H mov Z, lnc ax add ax, Turbo C mov ax, _y add ax, 0004H mov Z, ax コンパイラをチェックし , もし必要ならソ ースコードをアレンジするとよくなるかも しれない。この最適化をしない理由はどこ にもない コードの移動 ループの中て、変化しないコードはコード 移動 , すなわちホイスティング (hoisting: tmp ; 計算は , すべてループ外へ引き出し , 一度 巻き上げ ) の候補だ。ループ内て、変化しない while(x > tmp 最適化後 while(x > 最適化前 に計算可能だ。 同様のテクニックが多忙式 (very busy 路にわたり , 計算される同一のコードにも expression), すなわち条件文のすべての経 最適化前 あてはまる。 不思議なことに Watcom は変数 Y を st 目 en ( ) へのコールて、置き換えると正しく最適 44 CMAGAZINE 19 9 のはカッコを使って定数のある部分式をグ 化した。これに関連したケースが発生した ループ中て、一定のコードは削減量がルー プの繰り返し回数て、掛け算されるのて、重要 て、ある。多忙式は時間には無関係だが , ス ペースの削減に役立つのて、重要だ。ヒント をひとっさしあげよう。このような最適化 は自分て、なさい。どのコンパイラも抜きん 出たものはないし , このようにコーディン の展開 インラインコード グしない理由が私には思いあたらない mov ax, S2 mov di, offset buf strcat(buf, s2) 数 st 「 cat( ) の例て、ある。 は大きく異なる。以下は TopSpeedC て、の関 るコンパイラは少ないし , インプリメント 内部関数 (intrinsic function) をサポートす て、 , レジスタ利用も改善される。 スタへのベストな変数割り付けを行えるの 適利用することになる。コンパイラはレジ プラインとインストラクションキューを最 かまわなければコールをなくし , 実行バイ 換えたくなる。コードサイズが増加しても につれて , コールをインライン展開に置き グの比だ。コールオーバヘッドが増加する 全体に対するコールのプロローグ / 工ヒ。ロー コールオーバヘッドは , 関数の実行時間

10. 月刊 C MAGAZINE 1990年9月号

の仮定 ( —0a) が抜けている。これは , 工リア スがあるのにも関わらず , Ver. 5.1 て、一 Oa を指定しコンパイルして動いたプログラム が , Ver. 6.0 て、一 Oa を指定すると動かなく なる可能性があるためらしい。また , ノレー フ。最適化 ( ー (I) も安全な最適化のみを行うよ うになった。そのため Ver. 5.1 にあった On, 安全てないループ最適化は行わない というオプションはなくなっている。 デフォルトの最適化は今まて、同様、、一 0t" て、ある。安全て、ない最適化も含め , とにか くプログラムを高速化したい場合は一 Ozax ー G 「〃とやるとよい。ー G 「については 後述するが , 関数の呼び出し手順を fastcall にするオプションて、ある。 いくっかのプログラムをコンパイルし , MS-CVer. 5.1 の生成するオプジェクトと 比較してみると , Ver. 6.0 のオプティマイ ザがかなり賢くなっているのがわかる。 例として ,getnum という 10 進数の文字列を LiSt getnum ルーチン (getnum. c) 整数に変換する簡単なルーチンを使い , 生 1 : getnum(char *s) TabIe 2 Ver. 6.0 のオプティマイズオプション *s くニ オプション —Oa —Ow —Oz —Oe ー 09 —Oc —Op —Ox —Od —Oi —Ot —Os 内 工リアスがないことを仮定 関数の呼び出し時以外はエリアスがないことを仮定 ループ最適化 積極的な最適化 グローバルレジスタアロケーション グローノヾルな共通式のくくりだし プロックレベルの共通式のくくりだし 浮動小数点演算の一貫性を保証 最大限の最適化 ( ー Oegc ⅱ t ) 最適化しない 埋めこみ関数 インラインリターンを使わない サイズ優先 スピード優先 成コードの比較をしてみた (List 1 , 2 , 3 ) 。 この結果から , Ver. 6.0 は Ver. 5.1 に比べ ムダなレジスタへの代入が減っているのが わかる。これもグローバルレジスタアロケ ーションの効き目だろうか。 MS ー C は以前から C 言語流と Pascal 流の , ふたつの関数呼び出し手順をサポートして いた。 C 言語流に比べ Pascal 流は , 引数可変 個の関数が作れなくなるという制約がある 反面 , コードサイズや実行速度の点て、は有 利て、ある。 fastcall は PascaI 流の発展形て、 , はじめのいくつかの引数をレジスタて、渡す 呼び出し手順て、ある。レジスタて、渡せる引 数は , char, short, int, near ポインタなら 3 つ , long ならひとつまて、て、 , それ以上の引 数は今まて、どおりスタックに積まれて渡さ -f stcall ソースコ れるようになる。 ード中て、 fastcall というキーワー 3 : 4 : 5 : 6 : int num ニ 0 : while (*s while ()S > = ' 0 ' return(num) : Ⅱ *s num = num*10 ' ) S 十十 いまさら何て、 , と思うが tiny モデル .COM モデル ) が追加された。ー AT オプションて、モ デル指定すると COM ファイルが生成され る。不要メモリの解放などは COM モデル用 のランタイムルーチン側て、やってくれるよ うて、 , EXE モデルと同様に子プロセスの起 動などがて、きる。ただし , far ポインタを使 っているプログラムは tiny モデルにはて、きな いようて、ある。 インラインアセンプラ インラインアセンプラは QuickCVer. 2.0 に実装されたものとコンパチプルて、ある。 オペランドには C 言語て、使っているラベル , 変数 , 関数名などが使える。常駐型 ( TSR ) プ ログラムや割り込みハンドラを書くときに は非常に便利て、ある。例として int 25h を使 って物理的にディスクを読むルーチンの例 をあげよう (List 6 ) 。 なお , Ver. 6.0 からは cl コマンドて、アセン プラを呼び出せるようになった ( 与えたファ イルの拡張子が . ASM だと自動的にアセンプ ラを実行する ) のて、 , 本当のアセンプラを使 ったとしても , 以前よりは簡単にコンパイ ル , アセンプル , リンクて、きる。 basedfi インタ based'* インタは near, far, huge ポイン ドを使ってレジスタて、引数を渡す関数が記 述て、きる。また—Gr というオプションて、デ フォルトの関数呼び出し手順をレジスタ渡 し ( fastcall) にすることもて、きる。 なお Ver. 6.0 から , nea 「 , far, cdecl, pascal などのマイクロソフトが独自に定義 するキーワードには , その頭にアンダース コアがつくようになったのて、注意してほし い。コード実例を List 4 , 5 に示す。 メモリモテル 58 CMAGAZINE 19 9