游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2292|回复: 0

Athlon64汇编关键优化点

[复制链接]

63

主题

871

帖子

891

积分

高级会员

Rank: 4

积分
891
QQ
发表于 2004-12-14 11:03:00 | 显示全部楼层 |阅读模式
<1>内存大小失配(mismatches)
当不同的指令操作相同的数据时要避免内存大小失配
当一条指令读写了一个数据,随后另一条指令又读写
这个数据,则要保证数据是对齐的,而且保证两次都
以相同的大小读写
        EX:

        foo        DQ        ?        ; 假设是8B对齐的
        避免:
        mov        DWORD PTR foo, eax
        mov        DWORD PTR foo + 4, ebx
        mov        rcx, QWORD PTR foo
        或
        mov        foo, eax
        mov        foo + 4, ebx
        ......
        movq        mm0, foo
        建议:
        mov        foo, eax
        mov        foo + 4, ebx
        ......
        movd                mm0, foo
        punpckldq        mm0, foo + 4

<2>数据对象的自然对齐
读写对齐的数据至少在CPU的读写管线上耽搁一个时钟周期

        数据对齐规则:

        字(Word)                        地址能被2整除
        双字(Double Word)                地址能被4整除
        四字(Quad Word)                地址能被8整除
        十字节(Ten-byte)                地址能被8整除
        双四字(Double Quad Word)        地址能被16整除

<3>适当的内存拷贝程序

<4>分支的密度
尽可能使分支对齐,不要使她们交叉与16B边界
Athlon64可以对一个16B(对齐的)代码窗中的三
条分支指令预取,所以尽可能使分支对齐,并且
在一个16B代码窗中不要放置超过三条分支指令

        这些分支指令为:

        jcc        rel8
        jcc        rel32
        jmp        rel8
        jmp        rel32
        jmp        reg
        jmp        WORD PTR
        jmp        DWORD PTR
        call        rel16
        call        r/m16
        call        rel32
        call        r/m32

<5>预取指令
在读写大块连续内存时使用预取指令充分利用Athlon64的内存带宽

        这些指令为:

        读:        PREFETCH / PREFETCHT0 / PREFETCHT1 / PREFETCHT2
        写:        PREFETCHW
        无时间性:        PREFETCHNTA

<6>双字节近返回指令
使用双字节近返回指令可以提高性能,因为CPU无法对单字节近返回指令分支预测
在使用单字节近返回指令时要避免以下两种情况:

(1) 所有的分支跳转指令以单字节近返回指令为目标;
(2) 在单字节指令前直接放置条件跳转指令

最简单的双字节近返回指令是在返回指令前加上重复前缀,宏定义如下:
REPRET        TEXTEQU        <0F3H, 0C3H>

<7>直接路径(DirectPath)指令
尽可能使用直接路径(DirectPath)指令,不要使用矢量路径(VectorPath)指令
直接路径(DirectPath)指令在Athlon64的流水线上有更好的执行性能

<8>读取--执行 整数指令
使用读取--执行整合的整数指令代替读取和执行分开的整数指令,除非你要
配对流水线,读取--执行整合的整数指令大多数为直接路径(DirectPath)指
令,比分离的指令有更好的执行性能

<9>读取--执行 浮点操作数的浮点指令
同上,这样的指令可以提高性能,原因如下:
(1) 可以提高指令Cache的命中率;
(2) 更少的macro-ops,提高并行执行的机率
        EX:

        避免:
        movss        xmm0, [float_var1]
        movss        xmm12, [float_var2]
        mulss        xmm0, xmm12
        建议:
        movss        xmm0, [float_var1]
        mulss        xmm0, [float_var2]

<10>读取--执行 整数操作数的浮点指令
避免使用读取--执行整数操作数的X87指令,因为这样的指令为
矢量路径(VectorPath)指令,执行效率低
        EX:

        避免:
        fld        QWORD PTR [foo]
        fimul        DWORD PTR [bar]
        fiadd        DWORD PTR [baz]
        建议:
        fild        DWORD PTR [bar]
        fild        DWORD PTR [baz]
        fld        QWORD PTR [foo]
        fmulp        st(2), st
        faddp        st(1), st

<11>写合并(Write-combining)

<12>依赖随机数据的分支
避免依赖随机数据的分支,以提高分支预测的正确机率用条
件移动(cmovcc)和条件设置(setbcc)指令代替分支指令

<13>SSE和SSE2指令与数据
用相应的SSE和SSE2指令操作相应的数据类型,否则可能会降低效率

<14>不把数据与程序放在同一个64B Cache线
避免把数据与程序放在同一个64B Cache线,尤其数据会被改变
避免代码自修改和将代码放在数据段里,这些会导致L1 Cache
性能下降
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-23 16:30

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表