トップページ

本棚


両手で1000まで数えられますか?:2進法の話
数値 - 危険物取り扱い注意
100 × 200 =32?:変数のオーバーフローの話
パリティビット
小数の扱いについて
ぽいんた
ぽいんた2
ぽいんた3
ジ・オリジン
ジ・オリジン:補足
かっこつける話
かっこつける話2
文字列のこと
タイミングの話
拡張性の話
取り込む話
staticな話

コンパイルの話1
コンパイルの話2:止まらぬビルド
コンパイルの話3:マシン語に落ちるということ1:メモリの話
コンパイルの話4:マシン語に落ちるということ2:最適化
コンパイルの話5:マシン語に落ちるということ3:変数とスタック
コンパイルの話6:コンパイラはそもそも何をやってくれるのか??
リンクの話
プリプロセッサの話

OS、というもの

オブジェクト指向1
オブジェクト指向:2
オブジェクト指向:3

オブジェクト指向:番外 C言語のソースファイルの話
オブジェクト指向:番外 C言語での「再利用性」と「カプセル化」データ構造とアルゴリズム


抽象的な話

寝込んで布団の中で考えたこと
こんなの、常識??
お仕事プログラミング
ソフトでハードなプログラム
プログラムするということ
お勉強
プログラムを学ぶということの補足
C言語:「学問」と「実務」
統合開発環境
C言語ってポータブルですか?
C言語ってポータブルですか?:2
あなたは、どう読みますか?
ああ勘違い
試してガッテン
低級品
質問をするということ
ポカ
「何もしない」 != 「無駄」
エディタの話
もっと手を抜こう

いまどきの、アセンブラ

VisualStudio2005
VisualStudio2005:2

戦争の防ぎ方、に対する私の考え
身近な差別
改革
地球に優しいなんて大嘘
統計で嘘をつく方法

言葉について
言葉について:2

神が死んだということ
善悪の彼岸から、力への意思を目覚めさせるということ

本を読むということ
本を読むということ:2

絵を描く話
地図
地球儀

オカルトのお話
がんだむさん
RPGソフトウェア
記紀神話の不思議



メニュー

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

コンパイラには「最適化」という機能がある。

最近のコンパイラはこの最適化機能が優れているので、下手にアセンブラでプログラミングするよりもC言語あたりで書いたプログラムをコンパイルしたものの方が良かったりする。

石の方の命令系統も、最近のはC言語でコンパイルされることを前提に作られていたりするし。

いまどき、アセンブラが必要な場面ってどうしてもC言語などで表現できない(あるいはしにくい)局面でしかほとんど使用されていないのではないだろうか。


じゃあコンパイラの最適化って、どんなことをしてくれるのか?

大まかに言って、
①静的な演算
②無駄な処理の省略
と言う感じ。他にもあるけど。

具体的にどんなのっていうのは、
①の場合、例えば
unsigned int iHoge;
iHoge = 100*100;
なんてあった場合にいちいち実行時に計算するのは馬鹿馬鹿しいのでコンパイル時点で「10000」という値に置き換えてくれる。

上の例のように即値で見たら自分でやってもいいように見えるけど、定数を#defineしてるときとかもあるのでやっぱりありがたい。

他にもsizeof()演算子なども、①に含まれる。これは、前にも書いたけど。


②の場合は、ループ処理など。
int i, j, n;

・・・・

for(i = 0; i < 10; i++)
{
  j = i * 100 * m;
}
のようなソースがあった場合、「100 * k」はループ内で変更されることはない。それなのにkが変数であるために、①のように単純には置き換えができない。

こんなときは
int i, j, n, m;

・・・・
m = 100 * n;
for(i = 0; i < 10; i++)
{
  j = i * m;
}
のようなコードに置き換えられる。

また、同一の関数内で
if(i == TRUE)
{
  return;
}

・・・・

if(i == TRUE)
{
  ・・・・
}
なんて処理があった場合に、変数iに何も代入した形跡がなければ二つ目のif()は意味がないため、コンパイラはその部分を処理しない。

同様に
int i = 0;
i = 100;
と言う場合でも最初の0での初期化は無意味なため、省略される(初期化と代入の間に変数iを評価する処理があったら別だけど)。

他にも、代入されても一度も評価されない変数などは、その処理が省略されたりもする。


ただし、この最適化の処理はコンパイラの実装に依存する。
全てのコンパイラで同じような最適化処理が行われているわけではないことに注意。

さらに、コンパイラでは最適化できない(あるいはやりにくい)処理もある。

例えば、以下の多重ループ処理。
ここでは単純に、配列の中身を表示したいだけとする。
int i, j;
int array[10][100];
for(i = 0; i < 100; i++)
{
  for(j = 0; j < 10; j++)
  {
    printf("%d\n", array[j][i]);
  }
}
このソースで注意して欲しいのは、「array[j][i]」としていること。
上記の書き方では、メモリのアクセス効率が非常に良くない。

array[][]は二次元配列のように見えるけど、実際にメモリ上に確保されるのはひとつなぎの領域だ。上の例だと100byteが10個、の1000byteの領域と言うことになる(10byteが100個ではないのは、判るよね??)。

なので、上のようなループを組んでしまうと、メモリに飛び飛びにアクセスするため、とても効率が悪い。しかしながら、やむを得ずそうする必要があったのかそれともプログラマが間抜けなのかはコンパイラにはわからない。最適化したいけど、できないのだ。

素直に
int i, j;
int array[10][100];
for(i = 0; i < 100; i++)
{
  for(j = 0; j < 10; j++)
  {
    printf("%d\n", array[i][j]);
  }
}
となっていたら、array[][]は連続した領域なので、②によって最適化されるとループはひとつ、
for(i = 0; i < 10 * 100; i++)
で済む。さらに①を適用して、
for(i = 0; i < 1000; i++)
となる。

ぜんぜん違うでしょ??


このほかにもコンパイラはさまざまな最適化のノウハウを持っている。
だけど、それを適用してもらうにはプログラマの意図をコンパイラに判ってもらう必要もある。


プログラムを書くときに、最適化のことも多少考慮に入れて、最適化しやすい(コンパイラに優しい)ソースを書くようにしましょう。




| 新しいページ | 編集 | 差分 | 編集履歴 | ページ名変更 | アップロード | 検索 | ページ一覧 | タグ | RSS | ご利用ガイド | 管理者に問合せ |
@wiki - 無料レンタルウィキサービス | プライバシーポリシー