* 実行時間の短縮 
-ページ: [[The R Book ご意見]]
-投稿者: [[匿名]]
-優先順位: 低
-状態: 保留
-カテゴリー: 提案
-投稿日: 2004-05-30 (日) 21:44:41
-バージョン: [version]

** メッセージ 
私は,わかりやすいコードを書くことを推奨するものです。
トリックを弄すれば,若干の計算時間の短縮に寄与できる場合もあるでしょうが。
しかし,計算時間の短縮というのが,最適化する前の何分の一になりましたというのではなくて,というのは,同じように「実行時間が百分の一になりました」というのが100時間が1時間になったというのと100秒が1秒になりましたというのはまるっきり意味が違うと思うからです。揚げ足取りをすれば,後者のような場合に,別の解法を見つけるのに数時間かかったというのでは意味がないということです。
また,これは大部分の場合には該当しませんが,初心者に例示するような場合にはいきなり最適化したコードを見せても意味がないというか,教育的効果は望めないと言うことです(最適化の過程を見せればいいと言ういいわけはあるでしょうが,それにしても,そのコードが将来どれくらい使われて,総計としてどれくらいの時間節約になるのかというのを常に考慮しておくことは大事ではないでしょうか)

前置きが長くなってしまいましたが,対象とされている著書の中の例を取り上げて,最適化という問題を考えてみました。取り上げたのは,141ページのプログラムです。

例示されているプログラムは,実際の状況を反映している,初心者にわかりやすいコーディング例です。実際,「シャッフルする」とか「交互に配る」などというところは,心憎いばかりの配慮が見られます。ですから,初心者というか普通の人にはこのコーディング例は十分なものなんです。

これ以下の部分は,揚げ足をとるものではないですし,わざわざ記述すべき必要もないものです。私の立場とすると,「いろいろ最適化をするとこういうこともあるかもしれないが,だからどうなの?もとのママでいいじゃない」というスタンスです。

またまた,前置きが長くなりましたが,

もとのプログラム(の主要部分)を以下に示します。

 # 1:13がダイヤ, 14:26がクラブ, 27:39がハート, 40:52がスペードとする
 check <- function(x) {
 	alldia <- (max(x)<=13); allcrab <- ((min(x)>=14)&(max(x)<=26))
 	allheart <- ((min(x)>=27)&(max(x)<=39)); allspade <-(min(x)>=40)
 	(alldia &#x7c; allcrab &#x7c; allheart &#x7c; allspade)
 }
 
 list7.4.0 <- function(rep1) # 13.63
 {
 	pass <- 0; try <- 0
 	while(try < rep1) {
 		# シャッフルする
 		X <- rank(runif(52,0,1))
 		# 配る
 		p1 <- c(X[1],X[3],X[5],X[7],X[9])
 		p2 <- c(X[2],X[4],X[6],X[8],X[10])
 		if (check(p1)&#x7c;check(p2)) {
 			pass <- pass+1
 		}
 		try <- try+1
 	}
 	pass/rep1
 }
 system.time(list7.4.0(10000))

改訂版を以下に示します。
 check2 <- function(x)
 {
 	any(all(x <= 13), all((14 <= x) & (x <= 26)), all((27 <= x) & (x <= 39)), all(x >= 40))
 }
 
 list7.4.2 <- function(rep1) # 4.37
 {
 	pass <- 0; try <- 0
 	while(try < rep1) {
 		X <- sample(1:52, 10)
 		if (check2(X[1:5]) &#x7c; check2(X[6:10])) {
 			pass <- pass+1
 		}
 		try <- try+1
 	}
 	pass/try
 }
 system.time(list7.4.2(10000))

結果は,どうなったと思いますか

>  system.time(list7.4.0(10000))~
[1] 15.39  1.08 34.99  0.00  0.00

>  system.time(list7.4.2(10000))~
[1]  5.11  0.35 11.48  0.00  0.00

です。後者は,「トランプを配る」というところを変えただけです。
それで,実行時間が3分の1になったと評価するか,なんだ,3分の1になっただけかと評価するかは,読者に任せます。

今回示したコードには,「自分ならこう書くけどな?」と思うところがいくつかあるでしょう,しかし,根本的な所は私が示したところだけで,そのほかの所は「どうかいても結果は大差ない」のではないかと思います。

というか,「いやー,そんなことないぞ!!このプログラムなら○○分の1の時間でシミュレーションできるぞ」というのがあればここに掲載して頂ければ,勉強になります。
----
記事一見削除。[[Rコードの最適化例:トランプ]]参照
- 記事一見削除。[[Rコードの最適化例:トランプ]]参照
- x <- matrix(sample(1:52, 10*n, replace=TRUE), ncol=5) で,replace=TRUE とすると,トランプを配ってという条件に反します。これがあるので,試行回数をまとめることが難しくなっています。~
私もはまってしまったのです。system.time 関数で時間を測っていると,計算結果がどうなっているのか見過ごしがち。 --  &new{2004-05-31 (月) 09:03:03};
-そうでしたか。訂正版をそのうち公開しますといいたいところですが、正誤表作りに協力するという趣旨からずれてきていますね。著者も困るでしょうから、「おれならこうする」は「ご意見」とは別の頁にしましょう。 --  &new{2004-05-31 (月) 09:29:09};
-ご意見ありがとうございます。たしかに,高速化は大規模なシミュレーションでは大事で,今回の原稿ではその点には触れなかったことは反省しています。ただ,このトランプの例は,なるべく現実に起こる事態を忠実にイメージできるようなコードを示したかったので,わざわざ2人に交互に配るようにしたのです。実はシャッフルが現実通りではなくて,ランダムに並び替えられるので5枚ずつ配っても交互に配っても結果に影響しませんが,実際にシャッフルするときは何枚かずつ重なって動くので,配り方によって結果が変わりそうです。そういうコードを考えればよかったかもしれません。 -- [[中澤]] &new{2004-05-31 (月) 11:44:45};

#comment


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS