如何在 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
我有一个复杂的矩阵:
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