如何在 Fortran 90 中获得 nxn 矩阵的共轭?

How to get the conjugate of a nxn matrix in Fortran 90?

我有一个复杂的矩阵:

complex(rdp) :: a(:,:)

让我们假设这个矩阵是 nxn。如何共轭矩阵的每个条目?有一个内在的功能吗?

正如米奇评论的那样,有一个标量函数:https://gcc.gnu.org/onlinedocs/gfortran/CONJG.html

编译器应该能够轻松地在数组上对其进行自动矢量化;它只是对虚部的符号位进行异或运算。您不需要内在函数来利用 SIMD1.

无论如何,即时执行此操作非常便宜;对一个数组(或 2D 矩阵)做一个单独的循环只是为了应用这个操作可能不是一个好主意,除非你要重新读取这个数组 many 次。通过将共轭折叠到您接下来要做的任何事情中来增加您的计算强度(每 load/store 数据的 ALU 操作,或每次将其放入缓存中)。

或者缓存块你的矩阵并结合其中的一块,然后再将该块提供给下一个操作。


脚注 1: 尽管对于复数 real8,SIMD 仅在矢量宽度大于 128 位 = 16 字节 = 一个复数 real8 的大小时才有用。如果仅此而已,您还不如使用标量异或。如果不将结果用于任何其他用途,则 x86 编译器可以只使用 xor dword [rdi+12], 1<<31 给出指向 RDI 中复杂 real8 的指针。但是使用 AVX 或更宽的版本,您可以执行 256 位 vxorps 一次翻转两个复数 real8 中的高位。或者与 ARM SVE 类似。

Fortran 标准具有 CONJG 内在。方便的是,它是一个 elemental 内在函数,这意味着如果您为其提供数组参数而不是标量,它将对数组的每个元素进行操作。例如

program conjgtest
  use iso_fortran_env, only: real64
  implicit none
  real(real64) :: r(2, 4)
  complex(real64) :: c(2,2)
  call random_number(r)
  c = cmplx(r(:, 1:2), r(:, 3:4), real64)
  print *, c
  print *, "conjugate:"
  print *, conjg(c)
end program conjgtest