裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

メモリと計算時間のトレードオフ

2012年06月29日 | ブログラミング

DNA鑑定とバースデイ・パラドクス」にて

・対数を使うにしても、Rでやるにもn!;n=10^9とかになってくると、メモリの問題が出てくるようだ
・そんなのを少し回避しながら計算してみた

メモリと計算時間は互いにトレードオフの関係にある。
計算時間は掛かる(べらぼうに!でも許容範囲)がメモリは全く使わないプログラムを書けばよいだけだ。
このプログラムは引用元のプログラムが以下に無駄な計算をしているかを明示している。

func <- function(n) {
    q <- 4.7e12
    p <- 1
    for (i in 1:n - 1) {
        p <- p*(q-i)/q
    }

}

n = 10^i で i が 1 大きくなると,計算時間は 10 倍になる。
システム時間がほとんど掛かっていないところにも注目。

> for (i in 0:8) {
+     print(system.time(func(10^i)))
+ }
   ユーザ   システム       経過  
     0.001      0.000      0.000
   ユーザ   システム       経過  
         0          0          0
   ユーザ   システム       経過  
     0.001      0.000      0.001
   ユーザ   システム       経過  
     0.002      0.000      0.002
   ユーザ   システム       経過  
     0.018      0.000      0.018
   ユーザ   システム       経過  
     0.190      0.001      0.190
   ユーザ   システム       経過  
     1.941      0.011      1.939
   ユーザ   システム       経過  
    19.492      0.089     19.387
   ユーザ   システム       経過  
   196.289      1.623    196.516

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ダメ出し:ベクトル計算をしよう

2012年06月29日 | ブログラミング

DNA鑑定とバースデイ・パラドクス」にて

ns を 10^(seq(from=0,to=8,by=0.1)) に対して確率を求めているが,各 ns[i] について,毎回 1 からns[i] まで重複して計算をしている始めることになっている。無駄だ。
何を計算しているのか,よく考えよう。

> system.time({
+ # 4.7兆分の1の確率、と考えるための数字
+ q<-4.7*10^12
+
+ # 調べる人数(世界人口65億人だったり、日本人口1.2億人だったり、母集団100万人、10万人、1万人…など)
+ ns<- round(10^(seq(from=5,to=8,by=0.1)))
+
+ birthday<-rep(0,length(ns))
+ # 対数で計算しよう
+ # 同じ型のペアが少なくとも1組は存在する確率
+ for(i in 1:length(ns)){
+     birthday[i]<-1-exp(sum(log(1-1:(ns[i]-1)/q)))
+ }
+
+ plot(log10(ns),birthday,type="l",xlab="log10(人口)",ylab="すくなくとも同じ型のペアが1組ある確率")
+ })
   ユーザ   システム       経過  
    22.124     10.256     32.140

i = 1~1e8 まで,「1刻み」で各項に付加される確率 (q-i)/q, i=0, 1, 2, ... を計算しておき,cumprod して余事象の確率を求め,1 から引く。
さらに,この場合は対数で計算する必要はさらさらない(大きな数は出てこない)。
以下のようにすれば,計算時間は 1/3 になる

> system.time({
+ # 4.7兆分の1の確率、と考えるための数字
+ q <- 4.7e12
+
+ # 調べる人数(世界人口65億人だったり、日本人口1.2億人だったり、母集団100万人、10万人、1万人…など)
+ ns <- round(10^(seq(from=5,to=8,by=0.1)))
+ n <- 1e8
+
+ # 対数で計算する必要はない!!
+ # 同じ型のペアが少なくとも1組は存在する確率
+ birthday2 <- (1-(cumprod((q-0:(n-1))/q)))[ns]
+ plot(log10(ns), birthday2, type="l", xlab="log10(人口)", ylab="すくなくとも同じ型のペアが1組ある確率")
+ })
   ユーザ   システム       経過  
     6.135      3.136      9.195

> all.equal(birthday, birthday2)
[1] TRUE

> cbind(birthday, birthday2, birthday-birthday2)
         birthday   birthday2              
 [1,] 0.001063254 0.001063254  0.000000e+00
 [2,] 0.001684635 0.001684635  0.000000e+00
 [3,] 0.002668625 0.002668625  0.000000e+00
 [4,] 0.004226196 0.004226196  0.000000e+00
 [5,] 0.006689827 0.006689827  0.000000e+00
 [6,] 0.010581894 0.010581894  0.000000e+00
 [7,] 0.016719167 0.016719167  0.000000e+00
 [8,] 0.026368242 0.026368242 -1.110223e-16
 [9,] 0.041467409 0.041467409  0.000000e+00
[10,] 0.064919822 0.064919822  1.110223e-16
[11,] 0.100919658 0.100919658  0.000000e+00
[12,] 0.155157813 0.155157813  0.000000e+00
[13,] 0.234496703 0.234496703  0.000000e+00
[14,] 0.345260597 0.345260597  0.000000e+00
[15,] 0.488920866 0.488920866  0.000000e+00
[16,] 0.654868549 0.654868549  0.000000e+00
[17,] 0.814751459 0.814751459  0.000000e+00
[18,] 0.930901321 0.930901321  0.000000e+00
[19,] 0.985522844 0.985522844  0.000000e+00
[20,] 0.998784153 0.998784153  0.000000e+00
[21,] 0.999976020 0.999976020  0.000000e+00
[22,] 0.999999952 0.999999952  0.000000e+00
[23,] 1.000000000 1.000000000  0.000000e+00
[24,] 1.000000000 1.000000000  0.000000e+00
[25,] 1.000000000 1.000000000  0.000000e+00
[26,] 1.000000000 1.000000000  0.000000e+00
[27,] 1.000000000 1.000000000  0.000000e+00
[28,] 1.000000000 1.000000000  0.000000e+00
[29,] 1.000000000 1.000000000  0.000000e+00
[30,] 1.000000000 1.000000000  0.000000e+00
[31,] 1.000000000 1.000000000  0.000000e+00

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村