• 検索結果がありません。

CPU 仮想機械

ドキュメント内 アルゴリズム入門 (ページ 43-57)

43

44

代表的なプログラミング言語:

FORTRAN

 1950年代に開発された

アセンブリ言語が主流だった時代

 科学技術計算プログラムに用いられることが(今で も)多い

高性能なコンパイラがあったため

高性能な数値計算ライブラリが豊富なため

――行列計算・統計演算など

45

代表的なプログラミング言語: C

 1970年代初頭にUNIX OSとそのアプリケーショ

ンの開発のために作られた

ハードウェアを直接操作するようなプログラムを書ける

~~ アセンブリ言語に近い

それでいて高級言語 ~~ 色々なCPUで動く

 現在でも多くのソフトウェアの開発に利用

 安全性の配慮は少ない

脆弱性のあるプログラムを作ってしまいやすい

例: Morrisのコンピュータ・ワーム (1988)――用意した 配列よりも大きなサイズのデータを与えられると、他の データを破壊してしまう誤りを悪用

46

代表的なプログラミング言語: C++

 1980年代に開発

 Cにオブジェクト指向機能をとり入れた言語

オブジェクト指向以外の部分はCと同じ

 パーソナルコンピュータのOSやアプリケーション ソフトウェア開発の主流言語

例: Windows XP

47

代表的なプログラミング言語: Java

 1990年代中頃に開発

Webブラウザがダウンロードできるプログラムのための言語

として普及

互換性・安全性への配慮

 現在でも安全性や互換性が求められる場面で多く用い られている

Webサーバ上のアプリケーションプログラム

携帯電話にダウンロードするアプリケーションプログラム

(e.g., Androidアプリ)

 仮想機械による実行方式

 見た目はCやC++に似ている

48

Cプログラムの紹介

 モンテカルロ法による 円周率の計算

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(int argc, char* argv[]) { int n, m, i;

double x, y;

srand48(time(NULL));

n = atoi(argv[1]);

m = 0;

for (i = 0; i < n; i=i+1) { x = drand48();

y = drand48();

if ((x*x + y*y) < 1.0) { m += 1;

} }

printf("%f¥n", 4.0*m/n);

}

Cプログラム

def montecarlo(n) m=0

for i in 1..n x=rand() y=rand()

if x*x + y*y < 1.0 m = m + 1

end end 4.0*m/n end

def time(n)

puts Benchmark.measure{ montecarlo(n) } end

Rubyプログラム

mc.rb mc.c

複雑な処理を行うライブラリがある

(ライブラリを使う準備が必要)

乱数の生成・メッセージ表示など

変数は宣言してから使う

変数には型が付く

「int i;」=「iという名前の整数をしまう 変数を用意せよ」

値をしまうメモリの大きさを決めてお くため

計算の際に適切な機械語命令を選ぶた

←機械語では実数と整数の足し算は違う 命令

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(int argc, char* argv[]) { int n, m, i;

double x, y;

srand48(time(NULL));

n = atoi(argv[1]);

m = 0;

for (i = 0; i < n; i=i+1) { x = drand48();

y = drand48();

if ((x*x + y*y) < 1.0) { m += 1;

} }

printf("%f¥n", 4.0*m/n);

}

49

Cプログラムの特徴

実数の表示

乱数系列の 初期化

コマンド引数 の整数変換

mc.c

50

Cプログラムを実行してみよう

1.

プログラムを作る

エディタで入力(ファイル名:mc.c)

2.

コンパイルする

「ターミナル」で

gcc –O mc.c

入力

間違いがあるとエラーメッセージが行 番号とともに表示される

エラーが出なくなると機械語のプログ ラム(ファイル名:a.out)が作られる

3.

実行する

「ターミナル」で

./a.out

と入力す

c12345$ gcc -O mc.c

c12345$ ./a.out 1000000 3.140316

c12345$

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(int argc, char* argv[]) { int n, m, i;

double x, y;

srand48(time(NULL));

n = atoi(argv[1]);

m = 0;

for (i = 0; i < n; i=i+1) { x = drand48();

y = drand48();

if ((x*x + y*y) < 1.0) { m += 1;

} }

printf("%f¥n", 4.0*m/n);

}

mc.c

51

実行方式と速度

インタプリタとコンパイラは実行速度がどのくらい 違うか、モンテカルロ法による円周率の計算に要 する時間を比べてみよ

 時間の測り方

 Cの場合: time ./a.out

(ターミナルから)

 Rubyの場合: Benchmark.measure

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main(int argc, char* argv[]) { int n, m, i;

double x, y;

srand48(time(NULL));

n = atoi(argv[1]);

m = 0;

for (i = 0; i < n; i=i+1) { x = drand48();

y = drand48();

if ((x*x + y*y) < 1.0) { m += 1;

} }

printf("%f¥n", 4.0*m/n);

}

52

コンパイル実行方式と誤り

 Cプログラムに誤りを混入させ

てコンパイルし、コンパイラが どのような検査をしてくれるの かを調べてみよう

1. ここの

m = 0; をk = 0; に変え

てコンパイル(間違った変数名)

2. ここの

m = 0; をm = "abc"; に

変えてコンパイル

(数値のところ

に文字列)

 同様の誤りをRubyプログラム に混入させると何が起きるか?

プログラムのどこに誤りがある と言われるか?

mc.c

練習

 mc.c と mc.rb を書き換えて、コンパイル/実行時 のメッセージを比較してみよう。

cm12345$ gcc -O mc1.c

mc1.c: In function ‘main’:

: cm12345$ irb

irb(main):001:0> load("mc1.rb")

=> true

irb(main):002:0> montecarlo(1000000)

NoMethodError: undefined method `+' for nil:NilClass

54

アセンブリ言語プログラムを 見てみよう

1. 「ターミナル」で

gcc –O –m64 –S mc.c と入力する

→mc.cがコンパイルされ、アセンブリ言 語プログラムmc.sが作られる

2. Emacs等のエディタでmc.sを見る

55

アセンブリ言語プログラム

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char* argv[]) { int n, m, i;

double x, y;

srand48(time(NULL));

n = atoi(argv[1]);

m=0;

for (i = 1; i <= n; i++) { x = drand48();

y = drand48();

if ((x*x + y*y) < 1.0) { m += 1;

} }

printf("%f¥n", 4.0*m/n);

}

movl $0, %r13d m = 0

movl $1, %ebx i = 1

L5:

call _drand48

movsd %xmm0, -40(%rbp) x = drand call _drand48

movsd -40(%rbp), %xmm1 y = drand mulsd %xmm1, %xmm1 y^2

mulsd %xmm0, %xmm0 x^2

addsd %xmm1, %xmm0 x^2 + y^2 leal 1(%r13), %eax

movsd LC0(%rip), %xmm1 1.0

ucomisd %xmm0, %xmm1 x^2+y^2 < 1.0 cmova %eax, %r13d m += 1

incl %ebx i++

cmpl %ebx, %r12d i <= n

jge L5

L4:

mc.sの一部

機械語にすると どんな命令になるか?

56

おまけ: アセンブリ言語の

プログラムを書き換えてみよう

1. エディタを使ってmc.sの途中にある

「ucomisd %xmm0, %xmm1」を

「ucomisd %xmm1, %xmm0」に書き換える

意味: 比較するものの順序を入れ替える

→モンテカルロ法の不等号を逆にしたことに相当

2. 「ターミナル」で gcc mc.s と入力する

→mc.sを機械語にしたa.outが作られる

3. 「ターミナル」で ./a.out 1000000

入力して実行→結果の値は?

ドキュメント内 アルゴリズム入門 (ページ 43-57)

関連したドキュメント