Loading [MathJax]/extensions/tex2jax.js

ページ

2011年2月2日水曜日

RとFortranの演算速度の比較

そろそろFortranもお勉強しようかとおもい、プログラムをしてみることに!!

作業は、2地点間の距離と角度を求めるというシンプルなもの
ただ、データ数が多く、組み合わせが全部で22,232,390もある。

まずRでプログラミング
特に変なことはしていないと思いますが...

  1. Tree<-read.csv("TreePlot",header=T)  
  2. IncW3<-read.table("IncW3Th10S3",header=T,sep=" ")  
  3. IncW5<-read.table("IncW5Th10S3",header=T,sep=" ")  
  4. IncW11<-read.table("IncW11Th10S3",header=T,sep=" ")  
  5.   
  6. Tree<-as.matrix(Tree[,1:5])  
  7. IncW3<-as.matrix(IncW3)  
  8. IncW5<-as.matrix(IncW5)  
  9. IncW11<-as.matrix(IncW11)  
  10.   
  11. DistW3<-matrix(rep(NA,nrow(Tree)*nrow(IncW3)*7),ncol=7)  
  12. DistW5<-matrix(rep(NA,nrow(Tree)*nrow(IncW5)*7),ncol=7)  
  13. DistW11<-matrix(rep(NA,nrow(Tree)*nrow(IncW11)*7),ncol=7)  
  14.   
  15. for (i in 1:nrow(Tree)){  
  16.  for (j in 1:nrow(IncW3)){  
  17.  DistW3[i*j,1:4]<-c(Tree[i,4:5],IncW3[j,1:2])  
  18.  DistW3[i*j,5]<-sqrt((Tree[i,4]-IncW3[j,1])^2+(Tree[i,5]-IncW3[j,2])^2)  
  19.  DistW3[i*j,6]<-atan((Tree[i,5]-IncW3[j,2])/(Tree[i,4]-IncW3[j,1]))  
  20.  DistW3[i*j,7]<-atan((Tree[i,5]-IncW3[j,2])/(Tree[i,4]-IncW3[j,1]))*180/pi  
  21.  }  
  22.  for (j in 1:nrow(IncW5)){  
  23.  DistW5[i*j,1:4]<-c(Tree[i,4:5],IncW5[j,1:2])  
  24.  DistW5[i*j,5]<-sqrt((Tree[i,4]-IncW5[j,1])^2+(Tree[i,5]-IncW5[j,2])^2)  
  25.  DistW5[i*j,6]<-atan((Tree[i,5]-IncW5[j,2])/(Tree[i,4]-IncW5[j,1]))  
  26.  DistW5[i*j,7]<-atan((Tree[i,5]-IncW5[j,2])/(Tree[i,4]-IncW5[j,1]))*180/pi  
  27.  }  
  28.  for (j in 1:nrow(IncW11)){  
  29.  DistW11[i*j,1:4]<-c(Tree[i,4:5],IncW11[j,1:2])  
  30.  DistW11[i*j,5]<-sqrt((Tree[i,4]-IncW11[j,1])^2+(Tree[i,5]-IncW11[j,2])^2)  
  31.  DistW11[i*j,6]<-atan((Tree[i,5]-IncW11[j,2])/(Tree[i,4]-IncW11[j,1]))  
  32.  DistW11[i*j,7]<-atan((Tree[i,5]-IncW11[j,2])/(Tree[i,4]-IncW11[j,1]))*180/pi  
  33.  }  
  34. }  

結果
ユーザ   システム       経過  
  1522.730      1.510   1528.272 

約25分ぐらいですか

次にFortranの場合
コードはこちら
  1. program DistCalc  
  2.  implicit none  
  3.  real,dimension(1565,5)::Tree  
  4.  real,dimension(7146,3)::IncW3  
  5.  real,dimension(4952,3)::IncW5  
  6.  real,dimension(2108,3)::IncW11  
  7.  real pi  
  8.  real DistW3(1565*7146),AngW3(1565*7146)  
  9.  real DistW5(1565*4952),AngW5(1565*4952)  
  10.  real DistW11(1565*2108),AngW11(1565*2108)  
  11.  integer i,j   
  12.   
  13.  open(10, file='Tree')  
  14.  open(20, file='IncW3')  
  15.  open(30, file='IncW5')  
  16.  open(40, file='IncW11')  
  17.  read(10,*) ((Tree(i,j),j=1,5),i=1,1565) !iは行、jは列  
  18.  read(20,*) ((IncW3(i,j),j=1,3),i=1,7146)  
  19.  read(30,*) ((IncW5(i,j),j=1,3),i=1,4952)  
  20.  read(40,*) ((IncW11(i,j),j=1,3),i=1,2108)  
  21.   
  22.  do i=1,1565  
  23.   do j=1,7146  
  24.   DistW3(i*j) = sqrt((Tree(i,4)-IncW3(j,1))**2 + (Tree(i,5)-IncW3(j,2))**2)  
  25.   AngW3(i*j) = atan2((Tree(i,5)-IncW3(j,2)),(Tree(i,4)-IncW3(j,1)))  
  26.   end do  
  27.  end do  
  28.   
  29.  do i=1,1565  
  30.   do j=1,4952  
  31.   DistW5(i*j) = sqrt((Tree(i,4)-IncW5(j,1))**2 + (Tree(i,5)-IncW5(j,2))**2)  
  32.   AngW5(i*j) = atan2((Tree(i,5)-IncW5(j,2)),(Tree(i,4)-IncW5(j,1)))  
  33.   end do  
  34.  end do  
  35.   
  36.  do i=1,1565  
  37.   do j=1,2108  
  38.   DistW11(i*j) = sqrt((Tree(i,4)-IncW11(j,1))**2 + (Tree(i,5)-IncW11(j,2))**2)  
  39.   AngW11(i*j) = atan2((Tree(i,5)-IncW11(j,2)),(Tree(i,4)-IncW11(j,1)))  
  40.   end do  
  41.  end do  
  42.   
  43.  pi=4*atan(1.0)  
  44.   
  45.  open(50,file="DistW3")  
  46.  do i=1,1565  
  47.   do j=1,7146  
  48.   write(50,*) Tree(i,4), Tree(i,5), IncW3(j,1), IncW3(j,2),&  
  49.    DistW3(i*j), AngW3(i*j), (AngW3(i*j)*180)/pi  
  50.   end do  
  51.  end do  
  52.   
  53.  open(70,file="DistW5")  
  54.  do i=1,1565  
  55.   do j=1,4952  
  56.   write(70,*) Tree(i,4), Tree(i,5), IncW5(j,1), IncW5(j,2),&  
  57.    DistW5(i*j), AngW5(i*j), (AngW5(i*j)*180)/pi  
  58.   end do  
  59.  end do  
  60.   
  61.  open(80,file="DistW11")  
  62.  do i=1,1565  
  63.   do j=1,2108  
  64.   write(80,*) Tree(i,4), Tree(i,5), IncW11(j,1), IncW11(j,2),&  
  65.    DistW11(i*j), AngW11(i*j), (AngW11(i*j)*180)/pi  
  66.   end do  
  67.  end do  
  68.   
  69. end program DistCalc  

で結果はというと、一目瞭然ですね!!
$ f95 DistCalc.f90
$ ./a.out

real 3m20.994s
user 3m14.140s
sys 0m5.330s

今回の場合には、Fortranのコードを書くだけで結構時間がかかった(まだ初心者なので)ので、Rだけで作業しても良かったかもしれません。
ですが、今後のことを考えてもFortranをお勉強したほうが良いですね〜
できればC++もお勉強したいのですが...

2 件のコメント:

匿名 さんのコメント...

よくわからないのにコメント付けて申し訳ないですが,
for (i in 1:nrow(Tree)){
for (j in 1:nrow(IncW3)){
DistW3[i*j,1:4]<-c(Tree[i,4:5],IncW3[j,1:2])
  :
のようなところは,添え字が i, j のときに,対象 i と対象 j の距離と角度というつもりなのではないでしょうか?
結果を格納する場所の添え字に i*j を使ってしまっては,正しい場所に正しい結果が格納されないのではないでしょうか?
つまり,例えば i=3, j=4 のときも,i=2, j=6 のときも i*j=12 なので,i*j が 12 になる場合に同じ場所にどんどん上書きされていくことになりますね。必然,i=3, j=4 のときの結果は上書きされてなくなってしまいます。
R では,for を使わないでベクトル化演算を用いることで,格段の実行速度が得られますよ。

MH さんのコメント...

コメントありがとうございます。
たしかにご指摘の通りです。このコード自体も後に書き換えて,i*jを使わないように修正しています。

また,Rとの比較という点も,ご指摘のように結果はフェアでとは言いがたいですね。今後修正します。

ありがとうございました。