2012

円周率をモンテカルロ法で求める vol.3

Java

先日、モンテカルロ法で円周率を求めるプログラムをくんだ。

ちょっと気になることがあって確かめてみたら驚いた。

そのプログラムを振り返ってみよう。

はじめに二重ループを使ったシンプルなプログラム。

jp\yucchi\loop_motecarlo_pi\Loop_Motecarlo_PI.java

その実行結果は次のようになりました。

run:
Montecarlo PI :  3.144016
Montecarlo PI :  3.143836
Montecarlo PI :  3.140812
Montecarlo PI :  3.142616
Montecarlo PI :  3.141592
Montecarlo PI :  3.139224
Montecarlo PI :  3.143332
Montecarlo PI :  3.140608
Montecarlo PI :  3.141352
Montecarlo PI :  3.139116
Montecarlo PI :  3.140224
Montecarlo PI :  3.141696
Montecarlo PI :  3.144996
Montecarlo PI :  3.142304
Montecarlo PI :  3.14044
Montecarlo PI :  3.14482
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.141936500000001
Time : 1516ミリ秒
構築成功 (合計時間: 1 秒)

次に今時の PC はマルチコアが当たり前になってきてるので

並行処理をさせるように変更しました。

jp\yucchi\montecarlo_pi\Montecarlo_PI.java

実行結果は先ほどのプログラムを遙かに上回る結果となるはずだったんだけど・・・

run:
Montecarlo PI : 3.143472
Montecarlo PI : 3.141672
Montecarlo PI : 3.1408
Montecarlo PI : 3.140352
Montecarlo PI : 3.141668
Montecarlo PI : 3.13966
Montecarlo PI : 3.139112
Montecarlo PI : 3.142532
Montecarlo PI : 3.13982
Montecarlo PI : 3.143956
Montecarlo PI : 3.141428
Montecarlo PI : 3.138096
Montecarlo PI : 3.141932
Montecarlo PI : 3.143548
Montecarlo PI : 3.14172
Montecarlo PI : 3.141612
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.14133625
Time : 22172ミリ秒
構築成功 (合計時間: 22 秒)

(゜◇゜)ガーン

な、なんと 遙かに遅い!

ExecutorService でスレッドプール作って処理させるほうがコストが高くつく!

この程度の計算ならシングルスレッドでもいいみたい。

そこで時間のかかる処理を無意味に追加した場合どうなるか確認した。

次のコードをそれぞれのプログラムに追加した。

for (int k = 0; k < 10_000; ++k) {
    for (int n = 0; n < 10_000; ++n) {
        double p = k * n;
                p = Math.sqrt(p);
    }
}

その結果は次のようになった。

二重ループのプログラムでは

run:
Montecarlo PI :  3.138036
Montecarlo PI :  3.144924
Montecarlo PI :  3.139508
Montecarlo PI :  3.14336
Montecarlo PI :  3.140848
Montecarlo PI :  3.14178
Montecarlo PI :  3.141744
Montecarlo PI :  3.143868
Montecarlo PI :  3.14006
Montecarlo PI :  3.143568
Montecarlo PI :  3.137936
Montecarlo PI :  3.141968
Montecarlo PI :  3.143396
Montecarlo PI :  3.142736
Montecarlo PI :  3.137876
Montecarlo PI :  3.141624
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.141452
Time : 250579ミリ秒
構築成功 (合計時間: 4 分 10 秒)

時間が結構かかってますね!

平行処理プログラムでは次のようになりました。

run:
Montecarlo PI : 3.142172
Montecarlo PI : 3.140212
Montecarlo PI : 3.142544
Montecarlo PI : 3.14186
Montecarlo PI : 3.14264
Montecarlo PI : 3.143252
Montecarlo PI : 3.140788
Montecarlo PI : 3.140544
Montecarlo PI : 3.14346
Montecarlo PI : 3.144144
Montecarlo PI : 3.141128
Montecarlo PI : 3.140564
Montecarlo PI : 3.140828
Montecarlo PI : 3.13794
Montecarlo PI : 3.140336
Montecarlo PI : 3.141248
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.1414787499999997
Time : 32468ミリ秒
構築成功 (合計時間: 32 秒)

(^_^)v 速い! 

浮動小数点演算なんかをさせるとかなり違いがでるのかな?

なんでもかんでも並行処理させればいいってことじゃないのかなぁ・・・?

リソースモニターですべてのコアが 100% で動いてるのは圧巻だったけど

処理が遅くては本末転倒ですね。(^_^;)

Hatena タグ:

円周率をモンテカルロ法で求める vol.2

Java

昨日、モンテカルロ法にて円周率を求めるプログラムをつくった。

乱数シュミレーションとしては、まぁまぁの数値を導き出していると個人的には思った。

さらに精度を上げようとして何回か同じ処理をして平均値を取ればいいかな?と思い

次のようにプログラムを変更してみました。

はじめに二重ループを使い平均値を求めるプログラムを組んでしまって

非常に効率が悪いことに気が付いたのは秘密です。(;´Д`)

相変わらず汚いコードですが素人のやることですからプロフェッショナルな人は

優しく解りやすくご指摘くださればうれしいです。

jp\yucchi\montecarlo_pi\Montecarlo_PI.java

一億個の針を落として計算する処理を百万回して平均値をとってみました。

って・・・計算処理が終わってない( ̄。 ̄;)

しかたないから一億個の針を落とす計算処理を千回に変更してみました。

上記のソースコードの NEEDLE の値を 1000.0 に変更して実行してみました。

これでも終わりそうにないくらい時間がかかります。

不本意ですが計算処理回数を32回に変更しました。(..;)

実行結果は次のようになりほんの気持ち程度精度は上がりました。

run:
Montecarlo PI : 3.14146332
Montecarlo PI : 3.1416326
Montecarlo PI : 3.1415482
Montecarlo PI : 3.141632
Montecarlo PI : 3.14127944
Montecarlo PI : 3.14178148
Montecarlo PI : 3.1416116
Montecarlo PI : 3.14141588
Montecarlo PI : 3.1416632
Montecarlo PI : 3.14117084
Montecarlo PI : 3.14161116
Montecarlo PI : 3.14168484
Montecarlo PI : 3.14166664
Montecarlo PI : 3.14151984
Montecarlo PI : 3.14131844
Montecarlo PI : 3.14161456
Montecarlo PI : 3.14160796
Montecarlo PI : 3.14157636
Montecarlo PI : 3.14174076
Montecarlo PI : 3.14137984
Montecarlo PI : 3.14161576
Montecarlo PI : 3.14160444
Montecarlo PI : 3.14165568
Montecarlo PI : 3.14140136
Montecarlo PI : 3.1414314
Montecarlo PI : 3.14134932
Montecarlo PI : 3.14164312
Montecarlo PI : 3.14159468
Montecarlo PI : 3.141492
Montecarlo PI : 3.14139636
Montecarlo PI : 3.14149788
Montecarlo PI : 3.1414862
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.14153397375
構築成功 (合計時間: 22 分 47 秒)

時間に余裕のあるときに計算処理回数を増やしてみて結果を確認したいと思います。

ちなみにこの計算は Intel Core i7-2600K (3.4GHz) の CPU を積んだハードウェアでしました。

OS は、Windows 7 64bit 版です。

Dual Xeon 4 Core (3.0GHz) のシステムより2倍くらい速いです!

ハイエンドマシンをお持ちの方は是非試してみてくださいね。(ё_ё)

実行結果の合計時間: 22 分 47 秒ってのは使用した NetBeans 7.2 開発版での実行時の値です。

NetBeans 7.2 DEV

Hatena タグ:


円周率をモンテカルロ法で求める

Java

モンテカルロ法という乱数シュミレーションで円周率を導き出してみます。

半径 r の円の面積は PI * r^2 ですよね。

半径 r を 1 とした円を中心から十文字に四等分した右上の部分を使って円周率を求めます。

円の中心から辺の長さ 1 の正方形を重ねます。

正方形の中には4等分された右上の部分の扇形の円がきっちり半径 1 の状態であります。

この時 x 軸、y 軸の 1 の位置は重ねた正方形の辺の長さ 1 になりますね。

よって、正方形の面積 : 扇の面積 = 1 : PI / 4 となります。

したがって PI を求める式は次のようになります。

PI = 4 * 扇の面積/正方形の面積

プログラムは乱数を使ってこの正方形の中にたくさんの針を落とします。

針の落ちた位置が扇の中か外かで円周率を求めていくという力技の方法です。

落とす針の数が多いほど精度は上がる理屈ですが処理時間も増えてしまいます。

とりあえず試してみましょう。 

 

jp\yucchi\montecarlo_pi\Montecarlo_PI.java

実行結果は次のようになりました。

run:
Mathクラスによる円周率は 3.141592653589793
モンテカルロ法による円周率は 3.14185944
構築成功 (合計時間: 9 秒)

何回かやって見たのですが小数点以下3位くらいまでの精度しかでませんでした。

精度を上げるにはこの処理を数回(数万回?)繰り返して平均をとればいいのかなぁ・・・?

Hatena タグ:

はじめての Lambda vol.5

Java

Lambda のことをいろいろ軽く調べてきました。

Swing を使った GUI アプリでも Lambda は重宝されそうですね。

それでは Lambda を使った簡単な Swing アプリを作ってみました。

jp\yucchi\Swing_Lambda_1.java

これまでのコードと違う部分が2カ所ありますね。

Lambda を使うと無名クラスの生成記述を省略できてしまうんですね~(^_-)-☆

それでは本当にこれで動くのか確認してみます。

おおっ!動いてますね(^_^)v

Lambda を使った難しいことは解りませんがこんな簡単で便利なことは好きです!

少しずつ Lambda に慣れて JDK 8 を楽しめるようになれるといいなと思う今日この頃です。

Hatena タグ:


はじめての Lambda vol.4

Java

はじめての Lambda シリーズも4回目となりました。

今回は Method Reference を使ってみることにします。

Method Reference って名前のとおりメソッド参照です。

メソッドに対する参照だけです。

よって、はじめての Lambda vol.2 でのサンプルコードの最大値を求める部分を

Method Reference に置き換えることができます。

下記コードのように非常に簡潔になります。(^_^)v

jp\yucchi\hello_lambda_2\Hello_Lambda_2.java

Math::max の部分が Method Reference を利用したコードです。

こんなにすっきりしたコードで本当にちゃんと動くのか?

試してみました。

Method Reference

 

おおっ! ちゃんと動いてるじゃないか!

一時期、Method Reference に :: # どちらを使うかで熱い議論がなされていた。(今も?)

Java™ Platform, Standard Edition 8 Developer Preview with Lambda Support b 39 では

:: (ダブルコロン)が採用されているようです。

Java 8 で Lambda が実装されたら馴染みのない素敵なコードを見ることができるような気がします。

Hatena タグ:

« 古い記事 新しい記事 »