ARM frsqrts 是否需要与额外的 fmul 指令一起使用以进行牛顿迭代?

问题描述 投票:0回答:1

在 ARM 指令frsqrts的文档中,它说:

该指令将两个源 SIMD 和 FP 寄存器的向量中相应的浮点值相乘,用 3.0 减去每个乘积,将这些结果除以 2.0,将结果放入向量中,并将向量写入目标 SIMD和 FP 寄存器。

我将其解释为 yₙ₊₁ = (3 - xyₙ)/2 - 事实上,以下代码证明了这种解释:

.global _main
.align 2
_main:
    fmov d0, #2.0 // Goal: Compute 1/sqrt(2)
    fmov d1, #0.5 // initial guess
    frsqrts d2, d0, d1 // first approx

    mov x0, 0
    mov x16, #1 // '1' = terminate syscall
    svc #0x80   // "supervisor call"

但是,阅读关于反平方根的牛顿迭代,我发现迭代不是 yₙ₊₁ = (3 - xyₙ)/2,而是 yₙ₊₁ = yₙ(3 - xyₙ²)/ 2.现在,显然我可以将 frsqrt

 与其他指令结合使用来得到这个:

fmov d0, #2.0 // Goal: Compute 1/sqrt(2) fmov d1, #0.5 // initial guess fmul d2, d1, d1 // initial guess squared frsqrts d3, d0, d2 // (3-r*r*x)/2 fmul d4, d1, d3 // d4 = r*(3-r*r*x)/2
但是引入自定义指令似乎很奇怪,它只能让您实现目标的一半。我是否滥用了这条指令?

assembly arm newtons-method sqrt square-root
1个回答
0
投票
这代表了将倒数平方根的牛顿-拉夫森迭代完全传统地划分为简单的类似 RISC 的指令。

例如,在AMD的3dNow! x86 的指令集扩展,这就是指令

PFRSQIT1

 的功能(全面披露:这是我设计的)。此功能甚至不需要底层的 FMA 功能:它可以通过对现有乘法器进行轻微修改来实现,因为当按预期使用时,即作为倒数平方的 NR 迭代的一部分,结果接近 1.0根。

正如询问者推断的那样,

frsqrts

需要接收倒数平方根的当前估计的
square作为其源操作数之一。由于 frsqrte
 指令提供了 1/sqrt(x) 的估计,精确到大约 8 位,因此计算单精度倒数平方根将需要两次 Newton-Raphson 迭代。从概念上讲:

frsqrte est0, x // initial approximation, accurate to about 8 bits fmul est0_sq, est0, est0 // first NR iteration for reciprocal square root frsqrts tmp, est0_sq, x fmul est1, tmp, est0 fmul est1_sq, est1, est1 // second NR iteration for reciprocal square root frsqrts tmp, est1_sq, x fmul res, tmp, est1
此指令序列直接映射到相应内联函数的序列:

vrsqrte_f32()

vmul_f32()
vrsqrts_f32()

© www.soinside.com 2019 - 2024. All rights reserved.