我有一个复杂的矩阵,由下式给出:
complex(rdp) :: a(:,:)
让我们假设这个矩阵是nxn。如何对矩阵的每个条目进行共轭?有内在的功能吗?
答案 0 :(得分:1)
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
答案 1 :(得分:0)
正如Mitch所说,有一个标量函数:https://gcc.gnu.org/onlinedocs/gfortran/CONJG.html
编译器应该能够轻松地将其自动向量化到数组中;只是对虚部的符号位进行异或。您不需要内部函数即可利用SIMD 1 。
无论如何,即时执行此操作非常便宜;仅对数组(或2D矩阵)执行一个单独的循环以应用此操作可能是个坏主意,除非您要多次重复读取该数组多次。通过将共轭折叠为下一步操作,可以提高计算强度(每次加载/存储数据或将其放入缓存的ALU操作)。
或者在对块进行下一个操作之前对其进行缓存块化并对其进行共轭。
脚注1:
尽管对于复杂的real8,SIMD甚至仅在矢量宽度大于128位= 16字节=一个复杂的real8的大小时才有用。如果仅此而已,那么不妨仅使用标量xor。如果不将结果用于其他任何东西,则x86编译器可以仅使用xor dword [rdi+12], 1<<31
,而该指针指向RDI中的复杂real8。但是,对于AVX或更宽的版本,您可以执行256位vxorps
的操作,一次翻转两个复杂real8中的高位。或类似地使用ARM SVE。