【问题标题】:intersectRaySphere x86 fpu asm routine - how to optymizeintersectRaySphere x86 fpu asm 例程 - 如何优化
【发布时间】:2012-08-15 20:23:31
【问题描述】:

你好,我有一些 c 程序:

    inline float intersectRaySphere(float3* rayO, float3* rayV, float3* sO, float sR)
    {
    static float3 Q;

    Q = sub(sO,rayO);

    float cc = dot(&Q,&Q);
    float v = dot(&Q,rayV);
    float d = sR*sR - (cc - v*v);

    // If there was no intersection, return -1
    if (d < 0.0) return (-1.0f);
    // Return the distance to the [first] intersecting point
    return (v - sqrt(d));
    }

我试图用 x86 fpu asm 重写它并创建这样一个

    _asm_intersectRaySphere:; Function begin
    push    ebp                                     ; 0000 _ 55
    mov     ebp, esp                                ; 0001 _ 89. E5
    add     esp, -20                                ; 0003 _ 83. C4, EC
    mov     eax, dword [ebp+8H]                     ; 0006 _ 8B. 45, 08
    mov     ecx, dword [ebp+0CH]                    ; 0009 _ 8B. 4D, 0C
    mov     edx, dword [ebp+10H]                    ; 000C _ 8B. 55, 10
    fld     dword [edx]                             ; 000F _ D9. 02
    fsub    dword [eax]                             ; 0011 _ D8. 20
    fld     dword [edx+4H]                          ; 0013 _ D9. 42, 04
    fsub    dword [eax+4H]                          ; 0016 _ D8. 60, 04
    fld     dword [edx+8H]                          ; 0019 _ D9. 42, 08
    fsub    dword [eax+8H]                          ; 001C _ D8. 60, 08
    fld     st2                                     ; 001F _ D9. C2
    fmul    st0, st(0)                              ; 0021 _ DC. C8
    fld     st2                                     ; 0023 _ D9. C2
    fmul    st0, st(0)                              ; 0025 _ DC. C8
    fld     st2                                     ; 0027 _ D9. C2
    fmul    st0, st(0)                              ; 0029 _ DC. C8
    faddp   st1, st(0)                              ; 002B _ DE. C1
    faddp   st1, st(0)                              ; 002D _ DE. C1
    fld     dword [ecx]                             ; 002F _ D9. 01
    fmul    st(0), st4                              ; 0031 _ D8. CC
    fld     dword [ecx+4H]                          ; 0033 _ D9. 41, 04
    fmul    st(0), st4                              ; 0036 _ D8. CC
    fld     dword [ecx+8H]                          ; 0038 _ D9. 41, 08
    fmul    st(0), st4                              ; 003B _ D8. CC
    faddp   st1, st(0)                              ; 003D _ DE. C1
    faddp   st1, st(0)                              ; 003F _ DE. C1
    fst     dword [ebp-4H]                          ; 0041 _ D9. 55, FC
    fmul    st0, st(0)                              ; 0044 _ DC. C8
    fld     dword [ebp+14H]                         ; 0046 _ D9. 45, 14
    fmul    st0, st(0)                              ; 0049 _ DC. C8
    faddp   st1, st(0)                              ; 004B _ DE. C1
    fsubrp  st1, st(0)                              ; 004D _ DE. E1
    fxch    st3                                     ; 004F _ D9. CB
    fstp    st0                                     ; 0051 _ DD. D8
    fstp    st0                                     ; 0053 _ DD. D8
    fstp    st0                                     ; 0055 _ DD. D8
    ftst                                            ; 0057 _ D9. E4
    fwait                                           ; 0059 _ 9B
    fnstsw  ax                                      ; 005A _ DF. E0
    fwait                                           ; 005C _ 9B
    sahf                                            ; 005D _ 9E
    jc      ?_001                                   ; 005E _ 72, 07
    fsqrt                                           ; 0060 _ D9. FA
    fsubr   dword [ebp-4H]                          ; 0062 _ D8. 6D, FC
    jmp     ?_002                                   ; 0065 _ EB, 06

     ?_001:  
    fstp    st0                                     ; 0067 _ DD. D8
    fld1                                            ; 0069 _ D9. E8
    fchs                                            ; 006B _ D9. E0
     ?_002:  
    mov     esp, ebp                                ; 006D _ 89. EC
    pop     ebp                                     ; 006F _ 5D
    ret                                             ; 0070 _ C3
    ; _asm_intersectRaySphere End of function

经过测试,运行正常,c 例程大约需要 150 个周期(在我的 6 或 7 岁的奔腾 4),我的 asm 例程大约需要 66 个周期 (*) - 所以它是 不错的改进,但也许它还可以改进一点?

tnx

(*) 我在随机输入数据上测试时不太小心,所以 可能是“不相交”的原因 - 不涉及 sqrt

【问题讨论】:

    标签: optimization assembly x86 fpu


    【解决方案1】:

    我会替换这个:

    fstp st0
    fstp st0
    fstp st0
    ftst
    fwait
    fnstsw  ax
    fwait
    sahf
    jc ?__001
    

    通过这个:

    fcompp
    fstp st0
    fldz
    fcomip st0, st1
    ja ?__001
    

    fnstsw 不是很快,sahf 也不是很好,尤其是在 P4 上。如果您不能使用fcomi(即如果它必须在P1 或PMMX 上工作),您仍然可以通过直接在ax 中测试一下来跳过sahf

    【讨论】:

    • 似乎在 1 - 2 个周期内略有改善,有时很难说,因为我在不同的运行中以某种方式有不同的结果,有时是 68,例如有时是 65 - 与“经典”相同在 fpu 上标准化 - 有时 90 有时 80 :/ (例如,我使用 fld xyz fld xyz 存储的初始版本是 90,改进了一个 fld xyz 并且堆栈存储也是 90,但是当我测量初始值时它变成 80 - 有点奇怪)
    • @grungefightr 好的,这当然不会有太大帮助,但我预计会比这更多(可能需要 4 到 6 个周期)。
    • 好吧,没关系 - 我的测量结果不是那么精确,我只想了解 fpu 的一般概念 - 我仍然相信可能存在更多规则,你可以优化这样的 fpu 代码 - 但是没关系 - 有一天 l8ter 将购买带有 avx 的新处理器并尝试在 avx 下重写最重要的部分,现在我想训练为 l8er 做好准备;-)
    • 65 很好,(非常好)此外,当 'normalise' 这只是常见的添加,并且不做真正的几何计算工作时,需要 80(不要尝试使用棘手的 invsqry (29) - 也许会更快 - 还没有尝试过 sse 版本)[虽然 65 可能是因为我用这样的数据测试它,其中没有发生交叉并且没有调用 sqrt]
    • 顺便说一句,您不应该对随机数据进行真正的测试。我相当肯定,如果您一直在相同的真实数据上进行测试,这些数字会更有意义。而且它们可能也会更高 - 对于该平方根而言,65 实在是太低了,以至于大部分时间都不会发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 2014-03-08
    • 2011-07-08
    • 1970-01-01
    • 2021-09-14
    相关资源
    最近更新 更多