查看完整版本: [-- [ASM] 在优化中碰到的情况,想一并整理一下 --]

-> 同人游戏创作/Doujin Games Workshop -> [ASM] 在优化中碰到的情况,想一并整理一下 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

littlewater 2010-02-22 10:42

[ASM] 在优化中碰到的情况,想一并整理一下

早先碰到过机会
LINK:http://bbs.thproject.org/read.php?tid=73005,但是由于某些原因没弄下去

这次又是偶然的碰到,希望能够了解一下,大概是这样的:

有二段伪代码:
A:连读两次内存数据,立即处理指令

  1. xor al, byte read mem
    mov bl, byte read mem

B:先读取到寄存器,然后再进行处理

  1. mov cx, word read mem
    xor al, cl
    mov bl, ch

实现了相同的功能,那么理论上我应该考虑使用哪一个呢?
注:这里MEM的位置为一个字节大小1K以内TABLE

个人的想法:
(1) L2Cache:不知道CPU的L2cache是不是对整个块进行优化的,如果其中一个字节或者字或者双字被操作,是否整个MEM都会被选择到L2中去呢?
(2) 指令流水线:B方法明显需要先完成前一个mov然后同时处理后二者,而A方法没有依赖关系

另外顺带想到的:
(1) 对于这样的指令:

  1. mov al, ch
    mov cl, ah

CPU流水线会被打断吗?
(2) 对于这样的指令:

  1. xor bl, byte ptr [esi + 1 + eax * 4]

已知esi是4字节边界对齐的内存,会因此而降低读取效率吗?
(3) 对于这样的指令:

  1. mov ebx, dword ptr [esi + 1 + eax * 4]

已知esi是4字节边界对齐的内存,会因此而降低读取效率吗?

ryuka 2010-02-22 15:33
水水姐这问题..反正我什么都不知道.乱猜下.
猜一下:
AB方法;A (首先假设cpu数据总线是32位(4字节)的,假设mem和mem + 1都在同一块4字节内的内存里面,A方法load的时候会连带把mem 和 mem + 1所在的4字节块(1块)送cpu数据总线,在保留站里面同时处理完2个寄存器的load,比B方法少了中间寄存器的步骤,假设mem和mem+1是分别在2块4字节内存里面的,AB方法都要load2块,B方法应该还要做一次位移填充word)
(1):不会(数据肯定没冲突,资源可能冲突,但是寄存器高低部分应该有分开的读取口?? 猜的)
(2) 不会
(3) 会(CPU读了2块4字节的,给做了位移和加法)

Advance 2010-02-22 16:20
A快。只要刚好是在一个或多个CACHE LINE里面。没有互锁的两条指令较快
(1)跟流水线没有联系
(2)字节运算不考虑对齐
(3)没记错的话非对齐运算损耗约8~12倍性能

littlewater 2010-02-22 21:17
不是说前一条指令对EAX数据写入,下一条指令必须要等到这条指令执行后才可以继续吗?
我的理解一直就是读写上的瓶颈,所以才需要把几条指令调整一下位置……

uox 2010-03-07 11:23
引用第3楼littlewater于2010-02-22 21:17发表的  :
不是说前一条指令对EAX数据写入,下一条指令必须要等到这条指令执行后才可以继续吗?
我的理解一直就是读写上的瓶颈,所以才需要把几条指令调整一下位置…… [表情]



下一条指令没有需要知道eax值的进行判断的情况, 因此 不存在流水线打断的问题

关于内存操作 尽可能dword 对齐==, 读不对齐的dword 貌似很慢

sjmind 2010-03-07 12:03
理想状态下,A需要5+X~5+2X,而B需要6+X的时间,关键看有没有miss,但根据B可以推测不可能产生miss所以A比较快

1)只要不是山寨的CPU都保证不会切断流水线(即使做成以EXX作为碰撞标志,仍然可以通过forwarding避免切断流水线)
2)字节的话,其实无所谓的,不过传说中Intel有部分CPU会有一定影响(由于微编码导致的影响,会调整字节也先对齐),但是反正不会对总时间造成影响,直接可以无视,最重要的是,应该没人用那些型号的CPU了
3)字节以上务必要对齐,未对齐的话,实际上会中断流水,且位数越多损耗越大,尤其像双精度浮点操作,没有对齐的话,会增加数十倍的时间

littlewater 2010-03-07 16:59
uox大说的“进行判断”是指显示的指令判断呢,还是隐式的数据修改判断呢?

sjmind大说的“碰撞标志”是什么意思来着?- -

-----------------------------

感觉实际上给出的例子代码也许不足够长,可能可以根据机器的预测避免很多看似会中断的问题吧?
也许和后面的指令关系比较大^^||| 看来得再下回留意呢^^

sjmind 2010-03-08 10:28
CPU设计里面有个碰撞检测,指的是不同流水线阶段同时使用到相关的寄存器,在部分CPU(尤其是早期的)由于芯片集成度的问题,碰撞检测往往会比较低能,导致比如decode和execute阶段使用相同寄存器也会导致流水线中断(在早期Intel的超长流水线中这个问题也很严重),为了解决这个问题往往会采用forwarding技术,也就是用一些而外的储存单元临时存放与发送产生碰撞的寄存器的内容.
由于寄存器碰撞导致的流水中断发生情况已经相当少,甚至可能完全避免.
实际设计汇编程序的时候往往采用针对芯片的优化来避免此类问题,毕竟,很多芯片细节你是不知道的.

sjmind 2010-03-08 10:36
真的有挑战的手写汇编里面,其实跳转导致的中断问题才是真的复杂问题,如何从硬件或软件实现减少由于跳转导致的流水中断和cache miss实际上是各大高校的研究课题之一,而像碰撞、Cache miss这些问题现在考虑的人反而比较少,甚至几乎没有(尤其是多任务系统考虑cache miss往往是徒劳的,我们做OS的时候3个进程一起跑,有没有优化过的程序cache miss次数1%都不一定有,到后面编译的时候都懒得开优化选项的)

littlewater 2010-03-08 19:15
原来如此,SJMIND的意思是减少JMP类指令以及尽可能数据紧邻排布吗^-^?
因为因素较多,那么总结一下优化优先级就是:

Jmp类减少 > 流水线 >  指令数目 > L1 L2命中 > 碰撞预防

稍等,JMP这个指令本身是确定的是否影响到流水线^^?
还有我是否应该尽量使用JMP SHORT(而不是JMP)呢?
还有我已知JNZ等跳转的概率(譬如for里面90%以上是回跳),我是否有办法优化呢?

sjmind 2010-03-11 22:45
流水深度越大,导致的跳转损失越大,这个问题主要集中在条件跳转的预测分支上,简单的说,就是当一个跳转成立的时候,后续的(就是指内存顺序上的)指令已经都在流水线上了,这个时候需要清空无效区域,并且还要回滚状态(主要是把某些forwarding导致的问题解决)
跳转的另外一个问题在于跳转的距离,虽然说cache变大之后这个问题比以前小多了,但是仍然会出现大量长距离跳转导致miss率激增的情况
至于软件实现跳转预测,这个很难细节,因为有时候硬件会自作聪明的帮你预测(成功率就哪个啥了)但是一般推荐将大概率的block直接接在跳转之后
(risc芯片的话要注意,部分汇编的 slt系列 后面的第一条指令会被无条件执行,且无回退尤其是gas给mips32写程序)

littlewater 2010-03-12 09:19
直接接在跳转之后,是指尽量放置在不会跳转的情况下吗?
比如

  1. JNZ XXXXXX
         (more hit block)
    XXXXXX:
         (less hit block)


RISC那……是不是叫做那个Delayed-Execute 稍微了解过,不明白为什么要这么弄

sjmind 2010-03-12 17:05
就是那个样子

跳转失败的回滚是很复杂的一个东西,如果在risc里面做了这个模块就违反了risc的初衷了,所以risc采取即使跳转失败也不回滚的基本思想
顺带说一下,这个问题发生的根本原因是在进行跳转的时候(decode阶段)已经有一个指令装入流水线,如果不执行的话,会浪费一次地址访问,而risc的设计者们认为,这种浪费是不可容忍的

这学期正好在做计算机组成课程设计的助教,相当有怀旧感 —____________,—

littlewater 2010-03-12 21:46
有道理,就是说,如果设计充分,那样可以保证不会浪费任何指令^^

鸡蛋灌饼 2010-03-15 01:01
引用第11楼littlewater于2010-03-12 09:19发表的  :
直接接在跳转之后,是指尽量放置在不会跳转的情况下吗?
比如

  1. JNZ XXXXXX
         (more hit block)

RISC那……是不是叫做那个Delayed-Execute 稍微了解过,不明白为什么要这么弄
.......

没意义,现代x86用的是基于分支行为的动态分支预测。另外即使是在其他指令集上,想要搞针对分支的优化也要用prediction hints
GCC的扩展likely和unlikely就是搞这个的,不过,如前所述,这个对于现代x86处理器来说没意义

ps:想着怎么优化单线程,不如去看看怎么把多核利用起来。

littlewater 2010-03-15 19:10
没意义如何理解呢?

多核心是另外的话题吧^-^

sjmind 2010-03-16 14:38
其实是有意义的,动态预测一般做的时候仍然是在execute阶段反馈到BTB/BHT,这个时候必然有不下1条指令进入decode阶段,比如AMD的K7就是3条.这3条是要取消的.

同时一般动态预测观察一个跳转的最近4~16次行为,因此,低频跳转常常不具有可预测性,尤其是当跳转语句相当多的情况(AMD貌似是2k个记录,2000前Intel也是2k,现在不清楚)

顺带,现在讨论的是ASM,起码也得用GAS,GCC已经超出讨论范围了

多核优化的话,的确是个亮点,不过难度比较大
我做多核优化的话,一般都把问题map/reduce,不过有不少问题做不了这种优化.现在很多新的研究方向都在做非map/reduce的,不过比较可靠的论文米怎么看到,自己也蓝得去试,不过都在用ASM写了,是不是稍微烦了点?几个库调用起来直接用asm写的话还是很累的= =|||

littlewater 2010-03-16 19:28
Map Reduce 是什么^-^?

sjmind 2010-03-16 20:02
就是把 单线程问题 多线程 /  网格可计算 / 云可计算 化的某种方法论

littlewater 2010-03-17 19:18
不嫌烦的话……

网格可计算、云可计算 怎么理解^^

云计算感觉很深奥=x=


查看完整版本: [-- [ASM] 在优化中碰到的情况,想一并整理一下 --] [-- top --]


Powered by phpwind v8.7 Code ©2003-2011 phpwind
Time 0.021972 second(s),query:2 Gzip enabled