• 締切済み

ifortのベクトル化

こんにちは、プログラミング1年目の初心者です。 現在Fortranで書いたプログラムをifortで走らせているのですが、 do i = 1,ni x(i,j) = ... enddo ではベクトル化してくれるのに、 do j = 1,nj x(i,j) = ... enddo ではしてくれません。 これはこのコンパイラ独特の癖で、普通はベクトル化してくれるものなのでしょうか? また、この場合の j で do 文を回す何かしらのオプションがあるのか、 それともベクトル化の条件に当てはまるような工夫をしなくてはいけないのか、 ということも教えて頂けたらと思います。 よろしくお願いします。

みんなの回答

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

ベクトルプロセッサつきのマシンは使ったことがないのでわかりませんが、 do j = 1,nj x(i,j) = ... enddo こちらの場合、Fortranの配列の並び方ではとびとびの番地の要素に アクセスすることになりますが、 do i = 1,ni x(i,j) = ... enddo こちらでは連続する番地にアクセスすることになります。 この違いによって、ベクトル化する/されるの違いが出るのではないでしょうか? つまり > それともベクトル化の条件に当てはまるような工夫をしなくてはいけないのか、 こっちでしょう。 http://www.gfd-dennou.org/library/dcl/dcl-f77doc/doc_numaguti/math1/gaiyou/fortran.html の 多次元配列の記憶順序 の辺りを見てみてください。

reaven82
質問者

お礼

ご回答ありがとうございました。 番地云々の話は聞いたことがあったのですが、そこまで意識していませんでした。 なんとか工夫をしてみます。

関連するQ&A

  • fortran 配列受け渡し時の次元の一致

    fortran90、コンパイラはifortです。 普通メインプログラムとサブルーチン間での配列の受け渡しは、次元を揃えて渡すと思います。 とあるコード(以後コードA)を読んでいると、2次元配列を渡し、1次元配列で受け取っていました。 例 program test1 integer :: a(3,3) call testsub(a) end program subroutine testsub(b) integer :: b(9) end subroutine これが受け取り側でどう処理されているのかわからず、調べるために適当なテストコードを書きました。 a 123 456 789 ↓ b 123456789 になるとか 結果、コンパイルは通ったのですがサブルーチン側では全て0で置き換えられてしまいました。 コードAはpgiかなんかでコンパイルしていたようなのでコンパイラの違いでしょうか? よくわらなかったので質問させて頂きました。 質問をまとめますと、 (1)次元の異なる配列の受け渡しができるかどうか (2)その場合中身はどうなるか よろしくお願いします。 ---以下テストコード--- program testa implicit none integer :: a(3,3),i,j do i=1,3 do j=1,3 a(i,j)=j+(i-1)*3 enddo enddo do i=1,3 do j=1,3 write(6,*) a(i,j) enddo enddo call sub1(a) end program subroutine sub1(b) integer :: b(9),i do j=1,9 write(6,*) b(i),'sub' enddo end subroutine

  • fortran 行列ベクトル積

    行列ベクトル積を計算するプログラムを下のように書いたのですが、実行した結果の答えが実際計算した答えと異なります。初期の要素の設定がおかしいのでしょうか?教えて下さい。よろしくお願いします。 program list2_14 implicit none integer , parameter :: n = 2 real(8) a(n,n), x(n), y(n) integer i, j, k, l a(1,1:2) = (/1.2d0,3.4d0/) a(2,1:2) = (/5.6d0,7.8d0/) x(:) = (/9.0d0,10.0d0/) do i = 1, n y(i) = 0.0d0 do j = 1, n y(i) = y(i) + a(i,j) * x(j) enddo enddo do k = 1, n write(*,*) (a(k,l), l = 1, n) enddo write(*,*) x(:) write(*,*) y(n) end program list2_14 実行結果 1.2 3.4 5.6 7.8 9. 10. 128.4

  • 院試の問題(FORTRAN)で。

    FORTRANを昨日勉強し始めたばかりの初心者です。 とある大学院の試験問題でわからない部分があるので質問させていただきます。 問題文とソースは以下のとおりです。 以下のFORTRANプログラムについて、標準出力への出力を答えよ。 program main intger :: m(3,3),i,j,k,n n=3 m(1,1)=2; m(1,2)=1; m(1,3)=2 m(2,1)=2; m(2,2)=3; m(2,3)=12 m(3,1)=8; m(3,2)=-6; m(3,3)=2 do i=1,n-1 do j=i+1,n m(j,i)=m(j,i)/m(i,i) ← do k=i+1,n m(j,k)=m(j,k)-m(j,i)*m(i,k) enddo enddo enddo write(6,*) m(2,1),m(2,3),m(3,2),m(3,3) end これを計算していくとm(2,2)=0(計算ミスだったらすみません)となってしまって 上のソースの矢印の部分でエラーが出てしまうと思い、 それだと出力出来ないのではないかと思ったんですが、 それでは答えにならないので質問させていただきました。 コンパイラを使って実行してみたいのもやまやまなんですが、 なにしろ試験まで時間があまりないもので・・・ どなたか回答できる方いらっしゃいましたらよろしくお願いします!

  • fortranのデータ読み込み

    fortranで下記の読み込みたいデータがあります。 j k R(j,k) L(j,k) 1 1 5 1 1 2 10 2 1 3 15 3 1 4 20 4 2 1 25 5 2 2 30 6 データが9000行あるので, do i=1,9000 read(10,*) j(i) k(i) enddo のような読み込み方だと配列が大きすぎてだめなんです。 他の方法を知っている方、教えていただけませんか。 よろしくお願いします。

  • 配列のサイズが明示的でない計算について

    Fortranを例にとった場合、 行列A,Bの積Cを計算する場合、例えば以下のようなループで計算していました。(Fortran77) do i=1,10 do j=1,10 sum=0.0 do m=1,10 sum=sum+a(i,m)*b(m,j) enddo c(i,j)=sum enddo enddo それが今では、以下1行です。(Fortran95) c=matmul(a,b) 配列1つ1つの成分について計算する必要がないと言えそうです。Pythonなんかは全部こういう思想ですね。 プログラム言語はすべてこういう方向に進んでいるように思えます。 これがやや不安に思えるところがあります。配列のサイズを指定していないのでどこまで使って計算しているかわからないからです。 古い方(上段)では配列のサイズや上限を指定しているので、指定しているところより先がどうなっていてもとりあえず被害はありません。 しかし、サイズについてのケアがないと思いがけないような計算をしてくるんじゃないかと思うのですが。計算のバグ取のときここ大丈夫かな?となって疑心暗鬼ということにならないかと思うのですが。 配列の最大値なども関数1つと言う感じですが、どこまでの範囲での最大なの?と聞きたくなるわけですが。 いかがでしょうか。

  • アドバイスお願いします

    今,以下の様なプログラムを作っています. 正の整数nを上限とする数字の集合を考える. そのうち a*i+b*j で表現できない値の個数を出力する. a,bは事前に与えられた正の整数であり,i,jは正の整数の変数である. またa,b,nの取り得る最大値は1000000とする. とりあえずfortranで総当たりの方法で作ってみました. integer a,b,n,ans(1000000),c read(*,*)a,b,n  do i=1,n   ans(i)=i  enddo icount=0 do i=0,n  do j=0,n   c=a*i+b*j   if(c.le.n)then    do k=1,n     if(ans(k).eq.c)then      ans(k)=-1     endif    enddo   endif  enddo enddo do i=1,n  if(ans(i).gt.0)then   icount=icount+1  endif enddo write(*,*)icount end nの値があまり大きくなければ問題なく動くのですが, 最大値である1000000を入力して走らすと,とんでもなく 時間がかかってしまいます. もっとスマートな方法は無いものでしょうか? アドバイスお願い致します.

  • fortranを用いた行列の掛け算について

    行列の掛け算についてなのですが、ある行列aを2乗した行列bを求める場合は以下のようなプログラムを書けば出来たのですが、これを3乗以上に拡張するためにはどうしたらよいのでしょうか? ______do i=1,3 ________do j=1,3 __________b(i,j)=0.D0 ____________do k=1,3 ______________b(i,j)=b(i,j)+a(i,k)*a(k,j) ____________enddo ________enddo ______enddo

  • 並列化プログラムの作成方法について

    物理計算の並列化についてお尋ねします。計算機環境(GPU, メモリ分散(ハブ)、メモリ共有(CPU内での並列))、コンパイラの選択とかいろいろ条件があると思います。また、作りこみの度合い(本気度)によっても違うと思います。特に並列計算は並列化の度合いによって速度が急激に伸びるなどいろいろ特性があると思います。 現時点では、 通常のパソコン(Core-i7)で、コンパイラはintel fortran, OSはWindows10というごく普通の環境です。Cygwinのgfortran, Visual studioなどもあります。 物理プログラムは、構成として以下のようです。 2次元空間の時間発展の計算です。 do n=1,nt do i=1,nx ! x方向格子へのループ do j=1,ny ! y要綱格子へのループ enddo ! x方向格子ループの端 enddo ! y方向格子ループの橋 enddo ! 時間方向ループの終端 stop end 時間発展のループの中に、空間方向のループが何回も出てくるという構成です。計算が遅くなる理由は空間方向の格子数が極端に増えるからです。 このような場合、計算の速度を向上させるための並列化の方法についてゼロベースで教えて頂きたいのですが。ゼロベースなので、何から手を付けるべきかということですが。 よろしくお願いします。

  • ベクトルの問題がわかりません

    A=2i-2j+kのとき、A・X=3である この関係を満たすベクトルXを求めよ ちなみに答えはX=3i+j-kでした 解説をお願いします

  • Vectorの中のVectorについて

    現在Vectorを使ってプログラムを作っています。 その過程でVettorの中に違うVectorを追加していき、追加されたVectorのsize()を出したいのですが、どのように記述すればいいのかがいまいちわかりません。 というより、そもそもそういうことは可能なのでしょうか? 概要としては --------------------------------------------------------- String[] s ={"a","b","c","d","e","f","g","h","i","j"}; Vector v = new Vector(); Vector x = new Vector(); for (int i=0; i<=9; i++) { v.add(i, s[i]); } x.add(v); のように追加されたVectorの中のVetorの大きさ、つまりこの例なら結果としてVector vの中の要素の数10を出したいのです。 size()を使うのだとは思うのですが・・・・・・・・・。 どうすればVectorの中のVectorの要素数を返すことが出来るのでしょうか? ご教授していただければ幸いです。

    • ベストアンサー
    • Java