performance - 将屏蔽数组添加到另一个 Fortran 的最有效方法

标签 performance fortran

我有一个“屏蔽数组”,我想将其添加到另一个数组中——换句话说,我有 3 个数组, ABmask 。我的问题是,存储掩码(作为逻辑数组,作为 1 和 0 的真实数组)的最有效(就执行时间而言)方式是什么?

编辑

这是一个你可以玩的玩具程序(如果你有 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 -O3 -funroll-loops -ffast-math)
==== 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

当然,有一些事情可能会影响这一点——例如,编译器矢量化循环的能力——那么是否有关于如何实现这样的事情的经验法则?

最佳答案

为什么不使用“哪里”?

where (mask) A = A + B

可能使用 mask 最快,但唯一确定的方法是测量。

关于performance - 将屏蔽数组添加到另一个 Fortran 的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10737914/

相关文章:

可以使用数组参数从 Fortran 调用标量 C 函数吗?

loops - 在另一个循环停止的地方开始一个循环

mysql - JOIN中子查询(GROUP BY)最高效的过滤位置

javascript - this.key 与变量性能

python - 两个解决方案之间的运行时差异大 : Project Euler #14

fortran - 如何在 FORTRAN 中更快地写入二进制文件?

OPEN 语句中的 Fortran 语法错误

c# - SQLite .NET 性能,如何加快速度?

c# - 未使用的 "using"声明的开销?

compiler-errors - 嵌套函数: Error: CONTAINS statement at (1) is already in a contained program unit