用掩码对 Fortran 数组求和

Summing a fortran array with mask

我有一个 Fortran 数组 a(i,j)。我希望用一个 j 不等于 i 的掩码在维度 2(j) 上对它求和。

a1=0
do j=1,n
if(j.ne.i) then
a1=a1+a(i,j)
endif
enddo

使用 Fortran 中的内在求和函数执行此操作的方法是什么,因为我发现内在函数比显式循环快得多。 我想尝试 sum(a(i,:),j.ne.i),但这自然会出错。此外,如果有人可以建议如何仅使用 a(i,:) 的某些值,其中 abs(a(i,j)) 大于 0.01,这将很有帮助。

要回答您的最后一个问题,您可以使用 WHERE 构造来构建掩码。例如,

 logical :: y(3,3) = .false.
 real x(3,3)
 x = 1
 x(1,1) = 0.1
 x(2,2) = 0.1
 x(3,3) = 0.1
 print * , sum(x)
 where(abs(x) > 0.25) y = .true.
 print *, sum(x,y)
 end

这是否比嵌套的 do 循环更好是值得怀疑的。

您可以轻松避免非对角线情况的任何分支。它应该比创建任何掩码数组并检查掩码要快得多。即使分支预测非常有效,分支(条件跳转)也很昂贵。

do j=1,n
  do i = 1,j-1
    a1=a1+a(i,j)
  end do

  do i = j+1,n
    a1=a1+a(i,j)
  end do
end do

如果你需要你的代码既快又不短,你应该测试这种方法。在我的测试中它要快得多。

我发现对整个数组求和然后减去对角线元素的总和可以快 2 倍。

  a1 = 0
  do i = 1, n 
    a1 = a1 + a(i,i)
  end do 
  a1 = sum(a) - a1
  end do