私は別の配列に追加したい "マスクされた配列"を持っています。つまり、私は3つの配列A
B
とmask
を持っています。私の質問は、(実行時の点で)最も効率的なマスクを(論理配列として、1と0の実際の配列として)格納する方法です。マスクされた配列を別のFortranに追加する最も効率的な方法
EDIT
はここ(あなたはmpif77を持っている場合)あなたがで遊ぶことができますおもちゃのプログラムです:
program main
implicit None
include 'mpif.h'
integer, parameter :: ntry=10000
integer, parameter :: asize=1000000
real,dimension(asize) :: A,B,maskr
logical,dimension(asize) :: mask
real*8 :: dd,dt,dtave,dtbest
integer i
do i=1,asize
maskr(i)=mod(i,2)
mask(i)=.False.
if(mod(i,2).eq.0) mask(i)=.True.
enddo
A=1.0; B=1.0
dtbest=1d33
dtave=0.0
do i=1,ntry
dt=mpi_wtime()
call add_arrays_logical(asize,A,B,mask)
dt=mpi_wtime()-dt
dtbest=min(dt,dtbest)
dtave=dtave+dt
enddo
print*,"==== logical ==="
print*,"Average",dtave/ntry
print*,"Best",dtbest
A=1.0; B=1.0
dtbest=1d33
dtave=0.0
do i=1,ntry
dt=mpi_wtime()
call add_arrays_real(asize,A,B,maskr)
dt=mpi_wtime()-dt
dtbest=min(dt,dtbest)
dtave=dtave+dt
enddo
print*,"==== Real ==="
print*,"Average",dtave/ntry
print*,"Best",dtbest
A=1.0; B=1.0
dtbest=1d33
dtave=0.0
do i=1,ntry
dt=mpi_wtime()
where(mask) A=A+B
dt=mpi_wtime()-dt
dtbest=min(dt,dtbest)
dtave=dtave+dt
enddo
print*,"==== Where ===="
print*,"Average",dtave/ntry
print*,"Best",dtbest
end
subroutine add_arrays_logical(n,A,B,mask)
integer n
real A(n),B(n)
logical mask(n)
do i=1,n
if(mask(i))then
A(i)=A(i)+B(i)
endif
enddo
end
subroutine add_arrays_real(n,A,B,mask)
integer n
real A(n),B(n),mask(n)
do i=1,n
A(i)=A(i)+mask(i)*B(i)
enddo
end
マイ結果:
(のgfortran -O2)
==== logical ===
Average 1.52590200901031483E-003
Best 1.48987770080566406E-003
==== Real ===
Average 1.78022863864898680E-003
Best 1.74498558044433594E-003
==== Where ====
Average 1.48216445446014400E-003
Best 1.44505500793457031E-003
(のgfortran -03 -ffast-数学を-funroll-ループ)
==== logical ===
Average 1.47997992038726811E-003
Best 1.44982337951660156E-003
==== Real ===
Average 1.40655457973480223E-003
Best 1.37186050415039063E-003
==== Where ====
Average 1.48403010368347165E-003
Best 1.45006179809570313E-003
(pfg90 -fast) -
==== logical ===
Average 5.4871437072753909E-003
Best 5.4519176483154297E-003
==== Real ===
Average 4.6096980571746831E-003
Best 4.5847892761230469E-003
==== Where ====
Average 5.3572671413421634E-003
Best 5.3288936614990234E-003
非常に古いマシン上(pfg90 -O2) - 非常に例えば、ループをベクトル化するコンパイラの能力 - - 古いマシン
もちろん
==== logical ===
Average 5.4929971456527714E-003
Best 5.4569244384765625E-003
==== Real ===
Average 5.5974062204360965E-003
Best 5.5701732635498047E-003
==== Where ====
Average 5.3811835527420044E-003
Best 5.3341388702392578E-003
、これに影響を与える可能性がいくつかありますので、このような何かを達成する方法についての経験則がありますか?
私が扱っているコードはf77です(私の選択ではありません)。 – mgilson
そして、はい、私は時間を関数の中で過ごしたという意味です。私は編集します。 – mgilson
これは、私が本当に簡単にアクセスできる唯一のコンパイラであるため、 'gfortran'を使ってより速く答えることができます。しかし、このコードはあらゆる種類のコンパイラで実行されることを意図しています。この種のことのための経験則があります。親指のルールがない場合、恐らくそれについて心配する価値はありません... – mgilson