我有一个复杂的矩阵给出:
complex(rdp) :: a(:,:)
我们假设这个矩阵是nxn。我如何结合矩阵的每个条目?这有内在的功能吗?
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
正如米奇评论的那样,有一个标量函数:https://gcc.gnu.org/onlinedocs/gfortran/CONJG.html
编译器应该能够轻松地在数组上自动向量化;它只是对想象部分的符号位进行异或。您不需要内部函数来利用SIMD1。
无论如何,在飞行中这样做会非常便宜;除非你要多次重新读取这个数组,否则在数组(或2D矩阵)上进行单独循环只是为了应用这个操作可能是个坏主意。通过将共轭折叠成您下次执行的任何操作,增加计算强度(每次加载/存储数据的ALU操作,或者将其带入缓存)。
或者缓存阻塞矩阵并在将该块提供给下一个操作之前共轭一大块。
脚注1:虽然对于复杂的real8,SIMD甚至只适用于宽度大于128位= 16字节的矢量宽度=一个复数real8的大小。如果这就是你所拥有的,你可能只使用标量xor。如果没有将结果用于其他任何事情,x86编译器可以使用xor dword [rdi+12], 1<<31
给出指向RDI中的复杂real8的指针。但是对于AVX或更广泛的,你可以做一个256位的vxorps
,它可以同时翻转两个复杂的real8中的高位。或者类似于ARM SVE。