• 締切済み

計算速度

a(m,n) m=20000 n=10000 のとき do j=1,n do i=1,m x=x+a(i,j) end do end do の計算速度と do j=1,n do i=1,m x=x+a(j,i) end do end do の計算速度が違うのはなぜですか?

  • masics
  • お礼率92% (241/261)

みんなの回答

  • ok-kaneto
  • ベストアンサー率39% (1798/4531)
回答No.4

>キャッシュにヒットする確率が高くなる理由 「メモリアクセスの局所性」で調べてみてください。 時間的局所性、番地の局所性等。 似たようなことをしているのは↓ http://ja.wikipedia.org/wiki/%E5%8F%82%E7%85%A7%E3%81%AE%E5%B1%80%E6%89%80%E6%80%A7#.E3.83.A1.E3.83.A2.E3.83.AA.E3.81.AB.E3.81.8A.E3.81.91.E3.82.8B.E3.83.87.E3.83.BC.E3.82.BF.E3.81.AE.E5.B1.80.E6.89.80.E6.80.A7 レポートなら、丸写しはしないでね^^

masics
質問者

補足

回答ありがとうございます. レポートではないので,その点は安心してください.

  • ok-kaneto
  • ベストアンサー率39% (1798/4531)
回答No.3

レポートなら、なぜメモリー上に配置された順にアクセスすると早くなるのかを書いた方がいいでしょうね。 答えは「キャッシュにヒットする確率が高いから」です。 FORTRANでしょ?じゃあ間違いじゃないと思うけど。

masics
質問者

お礼

回答ありがとうございます. 少し理解が深まりました. おっしゃる通りFORTRANです. キャッシュにヒットする確率が高くなる理由まで知りたくなってしまいた.

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.2

別の例も作りました。 2重ループする際、10000×20000と20000×10000ではどちらが早いでしょう。 for ( int i = 0 ; i < 10000 ; i++ ) { for ( int j = 0 ; j < 20000 ; j++ ) { Sum+=x1[i][j]; } } for ( int i = 0 ; i < 20000 ; i++ ) { for ( int j = 0 ; j < 10000 ; j++ ) { Sum+=x2[i][j]; } } 前者が78ミリ秒後者が85ミリ秒でした。 理由はわかりますか?

masics
質問者

お礼

回答ありがとうございます.

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.1

プログラムが間違っているので、このままでは動きませんし、意図も伝わりません。 例えば、 for ( int i = 0 ; i < 10000 ; i++ ) { for ( int j = 0 ; j < 10000 ; j++ ) { Sum+=x[i][j]; } } と for ( int i = 0 ; i < 10000 ; i++ ) { for ( int j = 0 ; j < 10000 ; j++ ) { Sum+=x[j][i]; } } を比べるなら、 メモリーには[0][0],[0][1],[0][2],・・・[1][0],[1][1],[1][2]・・・と入っていますので、 前者はメモリーに並んでいる順に計算できるのに対して、 後者はメモリーをあちこちバラバラに計算しなくてはなりません。 時間を測ったところ、前者は0.04秒、後者は2.121秒でした。

masics
質問者

お礼

簡単にいうと以下のようなことですか? iから固定するならiを行にしたほうがよい.なぜならメモリーに並んでいる順番と計算の順番が同じだから.

関連するQ&A

  • (Σa_n・x^n)^m

    mを自然数として(Σ[n=0↑∞]a_n・x^n)^mが収束する場合にこれをべき級数で表した時のx^kの係数の計算の仕方がよくわかりません。a_nやxは実数とします。 Σ[n=0↑∞]Σ[n=n_1+n_2+…+n_m]a_n_1・a_n_2・…・a_n_m・x^nとして a_n_1・a_n_2・…・a_n_m=a_0^i_0・a_1^i_1・…・a_j^i_j・… と表すと有限個のjについてi_j>0でΣ[j=0↑∞]i_j=mであってnを固定するとこの係数をもつ項がm!/(i_1!・i_2!・…・i_n!)個あると考えればいいのかと思ったのですがこの推論は間違っているようです。 別のやり方としてx=0でのk次微分係数を計算してk!で割ればいいと思ったのですが具体的な計算ができませんでした。

  • ガウスの消去

    ガウスの消去法のプログラムを作ったのですがうまく動きません どこが間違っているのでしょう ちなみに連立方程式を解くプログラムです * the numerical solution of linear equation * by gauss method parameter(ll=10) dimension a(ll,ll+1), x(ll) read(5,100) n 100 format(i3) do 150 i = 1, n 150 read(5,200) (a(i,j), j=1, n+1) 200 format(11f4.1) write(6,300) 300 format(' ', 10x, 'coefficient') do 10 i = 1, n write(6,400) (a(i,j), j=1, n+1) 400 format(' ', 11 (5x, f4.1)) 10 continue esp=10.0e-19 call rgaule(a, x, ll, n, esp, ipivot) if (ipivot. eq. 1) go to 20 write(6,500) 500 format(' ', 10x, 'the pivot is little '/ 1 'so the solution is singular') go to 110 20 write(6,600) 600 format(/' ',2x, 8hsolution) write (6,700) (i, x(i), i = 1, n) 700 format (' ',5x, 'x (', i2, ' ) =', 2x, e14.7) 110 stop end subroutine rgaule(a, x, ll, n, esp, ipivot) dimension a(ll, ll+1), x(ll), ln(100) ipivot = 1 * the order of x do 5 i = 1, n ln(i) = i 5 continue do 100 m = 1, n-1 * the selection of pivot amax = 0.0 do 10 i = m, n do 20 j = m, n if (amax. ge. abs(a(i,j))) go to 20 amax = abs(a(i, j)) irow = i icolum = j 20 continue 10 continue if (amax. le. eps) go to 70 if (m. eq. irow) go to 22 * the exchange of row do 27 l = m, n+1 swap = a(irow, l) a(irow, l) = a(m, l) a(m, l) = swap 27 continue 22 if (m. eq. icolum) go to 30 * the exchange of colum do 25 l =1, n swap = a(l, icolum) a(l, icolum) = a(l,m) a(l, m) = swap 25 continue * the exchange of x iswap = ln(m) ln(m) = ln(icolum) ln(icolum) = iswap * gaussian elimination 30 do 35 i = m+1, n do 37 j = m+1, n+1 a(i,j) = a(i,j) - a(i,m) * a(m,j) / a(m,m) 37 continue 35 continue 100 continue if (abs(a(n,n)). le. eps) go to 70 * back subsititution x(n) = a(n, n+1) / a(n,n) kk = ln(n) a(n, kk) = x(n) do 50 i = n-1, 1, -1 k = n-i x(i) = 0.0 do 52 j = 1, k ll = i + j x(i) = a(i, ll) * x(ll) + x(i) 52 continue x(i) = (a(i, n+1) - x(i)) / a(i,i) kk = ln(i) a(n, kk) = x(i) 50 continue do 60 i = 1, n x(i) = a(n, i) 60 continue return 70 ipivot = 0 return end

  • FORTRAN 初心者です

    以下の連立一次方程式をSOR法で解く問題です。 初心者なりにガウスザイデル法を応用してプログラムしたつもりですが、やはり難しいです(答えは違います)。 どこをどうすれば良いのか分かりませんので、よろしければヒントや助言をいただきたいです。 PROGRAM SOR REAL A(10,10),B(10),X(10),X0(10) INTEGER N,I,J,K,Kmax,w N=3 A(1,1)=4 ;A(1,2)=1 ;A(1,3)=2 A(2,1)=1 ;A(2,2)=3 ;A(2,3)=1 A(3,1)=1 ;A(3,2)=2 ;A(3,3)=5 B(1)=16 B(2)=10 B(3)=12 X0(1)=1 ;X0(2)=1 ;X0(3)=2 w=1.2 Kmax=50 EPS=1.D-5 DO I=1,N D=A(I,I) S=B(I) B(I)=B(I)/D END DO DO K=1,Kmax DO I=1,N DO J=1,N if(J<I) X0(J)=X(J) S=S-A(I,J)*X0(J) END DO X(I)=(1-w)*X(I)+w*S END DO DO I=1,N S=S-(X(I)-X0(I))**2 END DO IF(S<EPS) GOTO 10 DO I=1,N X0(I)=X(I) END DO END DO 10 WRITE(*,*) K DO I=1,N WRITE(*,*) 'SOR法で求めた解は' WRITE(*,*) 'X(',I,')=',X(I) END DO END PROGRAM SOR !------------------------------------ ※wは緩和係数です

  • fortran errorについて

    fortranを勉強していたのですがエラーがでてしまい、何時間かけても理解できなかったので質問させてください。 以下プログラム program test !ここからメインルーチン !前準備 配列の用意 implicit none integer N integer,dimension(0:N,0:N) :: A integer :: i,j,k read * ,N !初期状態の代入 do i=0,N do j=0,N A(i,j)=0 end do end do do i=N/2,N-1 A(N/2,i)=1 end do do i=N/2,N-1 A(N/2+1,i)=-1 end do !ループ 50回ループさせる do k=0,50 !状態の表示 call visualize !サブルーチン visualize subroutine visualize do i=0,N do j=0,N if(A(i,j)== 1) write(*,'(A1)',advance='NO') "*" if(A(i,j)== 0) write(*,'(A1)',advance='NO') " " if(A(i,j)==-1) write(*,'(A1)',advance='NO') "+" end do write(*,*) end do !end subroutine visualize call insert !サブルーチン insert subroutine insert do i=0,N do j=0,N if(A(i,j)== 1) A(i,j)=-1 if(A(i,j)== 0) A(i,j)=max(0,A(i-1,j),A(i,j-1),A(i,j+1),A(i+1,j)) if(A(i,j)==-1) A(i,j)=0 end do end do !end subroutine insert end do end program test これでコンパイラすると In file test.f90:48 subroutine visualize 1 Error: Unclassifiable statement at (1) In file test.f90:69 subroutine insert 1 Error: Unclassifiable statement at (1) とでます いろいろ調べたのですが全くわかりませんでした できればよろしくお願いします

  • プログラムに内容と計算の質問です。

    こんにちは。 補間多項式についての、コンピュータのプログラムの解読に困っています。内容は、 「For the numerical experiments suggested in the computer problems, the following two procedures should be satisfactory. The first is called Coef. It requires as input the number n and tabular values in the array {Xi} and {Yi}. Remember that the number of points in the table is n+1. The procedure then computes the coefficients required in the Newton interpolating polynomial, storing them in the array{Ai}. -------------------------------------------------------- procedure; Coef(n,{Xi},{Yi},{Ai}) real array; {Xi}0:n, {Yi}0:n, {Ai}0:n integer; i,j,n for i=0 to n do {Ai}←{Yi} end for for j=1 to n do for i=n to j step -1 do Ai←({Ai}-{Ai-1})/({Xi}-{Xi-j}) end for end for end procedure Coef --------------------------------------------------------- このプログラムのn=3の時を考えるとき、  (1)j=1のとき、i=3,2,1 <j=1,i=1> {A1}=({A1}-{A0})/({X1}-{X0}) =({Y1}-{Y0})/({X1}-{X0}) <i=1,i=2> {A2}=({A2}-{A1})/({X2}-{X1}) =({Y2}-{Y1})/({X2}-{X1}) <i=1,i=3> {A3}=({A3}-{A2})/({X3}-{X2}) =({Y3}-{Y2})/({X3}-{X2}) (2)j=2のとき、i=3,2 <j=2,i=1> A1=({A2}-{A1})/({X2}-{X0})          ={[({Y2}-{Y1})/({X2}-{X1})]-[({Y1}-{Y0})/({X1}-{X0})]}/({X2}-{X0}) =この式変形をしたいのですが、どのように         すれば良いのかわかりません。ラグランジェ         型になりそうでなりません(泣)         (1)で求めた{A1},{A2},{A3}を使って求めな         いといけないみたいです。 見にくい表し方で申し訳ありません。 アドバイスお願いします!!

  • MATLABの計算過程での質問です。

    はじめまして。 MATLABのコードでどうしてもわからないことがあり質問させていただきます。 問題はerrorの計算で起こります。 error=Σ[((F_n+1)-(F_n))/(F_n+1)] ループ内の計算がiter=1以降に進まなくなりました。 いろいろ編集してみましたが、どうしてもerrorのところがうまく働きません。 良かったらアドバイスよろしくお願いします。 tol=tolerance N=number of maximum iterationです ---------------------------------------------------------------- tol=0.01; N=100; A=zeros(26,26); f0=zeros(26,26); A(11:26,1)=100; A(26,1:16)=100; f=A; iter=1;f0=0 n=1; for n=1:N for i=2:26-1 for j=2:26-1 f(i,j)=(1/4)*(A(i+1,j)+A(i-1,j)+A(i,j+1)+A(i,j-1)) error(i,j)= sum(abs((f(i,j)-f0(i,j))./f(i,j))); end end if error <=tol break; else A=f; f0=f; iter=iter+1 end end

  • 行列の計算

    #include<stdio.h> #define N 2 #define M 3 void hyoji(float[][M]); int main(){ int i,j,k; float a[N][M] = {{2.0,2.0,2.0},{2.0,2.0,2.0}}; float b[M][M] = {{1.0,1.0,1.0},{2.0,2.0,2.0},{1.0,1.0,1.0}}; float c[N][N]; for(i=0; i<N; i++){ for(j=0; j<M; j++){ c[i][j] = 0; for(k=0; k<M; k++){ c[i][j] += a[i][k] * b[k][j]; } } } hyoji(c); return(0); } void hyoji(float x[][M]){ int i,j; for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%4.1f ",x[i][j]); } printf("\n"); } } 以上のプログラムで 行列aと行列bをかけ合せた行列cを求めるのですが コンパイルすると 8 8 8 8 8 1 となり、正しい結果がでません。 なにが間違っているのでしょうか?? よろしくお願いします。

  • C言語への翻訳お願いします

    以下の文はある本から抜粋してきたガウス・ジョルダン法のサブルーチンです。Cに翻訳してくださいって言ったら怒りますか?(笑 c Gauss-Jordan method subroutine gj(a,n1,nn,m,epsl,isw) double precision a,epsl,p,w dimension a(n1,*) nplsm=nn+m do 100 n=1,nn p=0.0 do 10 i=n,nn if(p.lt.abs(a(i,n))) then p=abs(a(i,n)) ip=i end if 10 continue if(p.le.epsl) then isw=1 write(6,*) 'error' return end if do 20 j=n,nplsm w=a(n,j) a(n,j)=a(ip,j) 20 a(ip,j)=w do 30 j=n+1,nplsm 30 a(n,j)=a(n,j)/a(n,n) do 40 i=1,nn if(i.ne.n) then do 45 j=n+1,nplsm 45 a(i,j)=a(i,j)-a(i,n)*a(n,j) end if 40 continue 100 continue isw=0 return end だいたい自分でもCに書き換えることはできたんですが、次のところがどのように書き換えたらよいのか分かりません。 subroutine gj(a,n1,nn,m,epsl,isw), dimension a(n1,*), do 20 j=n,nplsm w=a(n,j) a(n,j)=a(ip,j) 20 a(ip,j)=w どうかよろしくお願いします。

  • 積分の計算問題なのですが

    ∫[0→1]x(1-x)^ndx と ∫[0→1]x^m(1-x)^ndxを求めろという問題があります(ただしm、nは0以上の整数) I1.n=∫[0→1]x(1-x)^ndxとおいてこれを計算するとI1.n=1/n+1・1/n+2となります Im.n=∫[0→1]x^m(1-x)^ndxとおいて計算すると Im.n=m/n+1・Im-1.n+1    =m/n+1・m-1/n+2・Im-2.n+2 =m/n+1・m-1/n+2・・・・・・・・1/n+m-1・I1.n+m-1となり 最終的に I m.n=m/n+1・m-1/n+2・・・・・・・・1/n+m-1・1/n-m・1/n+m+1 =m!/(n+m+1)! となってしまったのですが回答には I m.n=m!n!/(n+m+1)!とあります。 わかりづらくてすいませんがこの計算のどこが間違っているのか教えてくれませんでしょうか

  • fortran allocateを使って配列宣言を

    今変数 aについて考えています.aは i,jの2次元の座標におけるデータです. a(1,1)は10個配列を持ちたい a(1,2)は5配列を持ちたい a(i,j)はn個配列を持ちたい このような場合どのように配列を定義すれば良いのでしょうか? 例えば 2次元の大きさが3x3の場合で,それぞれの位置に配列したいデータ個数をnとします. nには既に個数が定義されているとします.このとき aの配列は nを使ってどのように定義すれば良いのでしょうか? integer n(3,3) integer i,j real, allocatable :: a(:,:,:) do j=1,3 do i=1,3 n(i,j)=i*j end do end do do j=1,3 do i=1,3 allocate (a(n(i,j),3,3)) end do end do では aの宣言が重複するためエラーになってします. 何方か良い方法を教えて下さい.

専門家に質問してみよう