POPPUR爱换

标题: Arm vs X86的论文 [打印本页]

作者: Tempestglen    时间: 2013-3-10 13:31
提示: 作者被禁止或删除 内容自动屏蔽
作者: raini    时间: 2013-3-10 13:37
笑死了!
作者: Tempestglen    时间: 2013-3-10 13:41
提示: 作者被禁止或删除 内容自动屏蔽
作者: the_god_of_pig    时间: 2013-3-10 13:45
吃饱了撑的
作者: darkangel308    时间: 2013-3-10 13:55
你的结论似乎一早就有人告诉过你吧,但是你从来都不信,非要说arm优于x86
作者: frankincense    时间: 2013-3-10 13:57
T神曾经声称架构决定x86这过气的CISC功耗永远都不可能赢ARM,而ARM使用的先进的RISC只要愿意,就能保持低功耗在性能上革x86的命,这些教诲尤在耳边啊。
作者: potomac    时间: 2013-3-10 14:24
提示: 作者被禁止或删除 内容自动屏蔽
作者: wuhao911    时间: 2013-3-10 15:08
呃,t神谈英文水平,谈学术素养?这个这个,本世纪最大的笑话诞生了。t神看不懂自己转的英文连接不是第一次了吧?那t神转的连接抽了自己的脸的事情恍若昨天啊,t神,您的雅思多少分来的?
作者: Tempestglen    时间: 2013-3-10 15:28
提示: 作者被禁止或删除 内容自动屏蔽
作者: eternal0    时间: 2013-3-10 16:18
全面对抗?
等什么时候ARM能运行现有Windows x86程序再说吧,对于绝大部分用户来说,跑不了Windows的笔记本电脑无异于玩具。
至少现在Atom运行大部分Android应用是没问题的。
作者: lz20062336    时间: 2013-3-10 16:35
一篇会议论文,水平不高,也不一定很严谨。
作者: xx88xx88    时间: 2013-3-10 17:02
T神啊,这篇论文是明显枪Intel的啊,你还转过来打自己的脸玩?
不过也不怪你,你的英语水平一直看不出Anand是枪Intel的,结果脸被当众打肿了。
这次也是那啥改不了那啥。
作者: kinno    时间: 2013-3-10 18:12
事到如今低能的arm再也不低耗了
作者: Episar    时间: 2013-3-10 18:57
听风就是雨,这话对发帖人来说,很合适!
作者: Prescott    时间: 2013-3-10 20:00
我一直说的就是这个啊,可惜T神不信。
至于敢和Intel拼微架构设计、制造工艺、编译器优化三项全能的公司,这个世界上还没有。其他公司统统加起来,也不够和Intel拼这三项全能。

作者: frankincense    时间: 2013-3-10 20:18
Prescott 发表于 2013-3-10 20:00
我一直说的就是这个啊,可惜T神不信。
至于敢和Intel拼微架构设计、制造工艺、编译器优化三项全能的公司, ...

Intel的驱动程序超不给力啊!
作者: eternal0    时间: 2013-3-10 20:28
frankincense 发表于 2013-3-10 20:18
Intel的驱动程序超不给力啊!

这帖子也没讨论显卡啊!
作者: potomac    时间: 2013-3-10 20:56
提示: 作者被禁止或删除 内容自动屏蔽
作者: FENG950    时间: 2013-3-10 21:02
本帖最后由 FENG950 于 2013-3-10 21:02 编辑

这里的人一向都如此认为的吧?说白了就是公司实力的较量,技术市场都如是。
作者: popboy139    时间: 2013-3-10 21:03
Prescott 发表于 2013-3-10 20:00
我一直说的就是这个啊,可惜T神不信。
至于敢和Intel拼微架构设计、制造工艺、编译器优化三项全能的公司, ...

在 PC平台上可以说编译器优化intel无敌 但是在android上不行吧 毕竟大型软件都是本地代码的  而且是针对ARM优化的 X86要运行只能转码 效率很低 BUG也很多 只能期待intel跟google多多沟通了
作者: junychen    时间: 2013-3-10 21:42
2014年就是主战场了 windows blue 平板上 ARM与X86阵营的对决
20nm VS 14nm 到时就会揭晓  不过A15的性能出来 确实是大跌眼镜。
就看 20nm A15能降低多少功耗了。
Intel至少有牛逼工艺撑着,加上乱序执行 性能应该不错 就是 GPU 驱动烂罢了。
只怕到时性能功耗比 是x86 略强。
作者: frankincense    时间: 2013-3-11 08:11
popboy139 发表于 2013-3-10 21:03
在 PC平台上可以说编译器优化intel无敌 但是在android上不行吧 毕竟大型软件都是本地代码的  而且是针对A ...

Google在Android 4.x上已经基本解决x86的本地代码问题了,当然效率如何还不得而知,现在效率应该不会比JIT差就是了。
作者: Prescott    时间: 2013-3-11 09:47
frankincense 发表于 2013-3-10 20:18
Intel的驱动程序超不给力啊!

HD系列的并不是太差吧,问题比较多的都是PowerVR核心的。
作者: boris_lee    时间: 2013-3-11 20:00
我是来围观自抽的
Large performance gaps exist across the implementations
作者: Tempestglen    时间: 2013-3-11 22:41
提示: 作者被禁止或删除 内容自动屏蔽
作者: wuhao911    时间: 2013-3-12 13:06
T神您到底看懂原文了没阿
作者: 芦鹏Coolboy    时间: 2013-3-12 13:23
本帖最后由 芦鹏Coolboy 于 2013-3-12 13:26 编辑

ARM 的load/store指令有天然的省电优势。不用频繁从内存调数据。
X86是3指令汇编 说白了每条指令都得玩内存。想省电确实难度大。
根子上是这问题。
ARM 平均大概5-10条汇编指令才调一下内存数据。
X86  平均大概1-2条汇编指令就调一下内存数据。这也是X86对内存带宽敏感,而ARM对内存带宽不敏感的原因。
X86就是一开始P6架构玩高性能把自己架上去下不来了。

作者: largewc    时间: 2013-3-12 13:37
本帖最后由 largewc 于 2013-3-12 13:55 编辑
芦鹏Coolboy 发表于 2013-3-12 13:23
ARM 的load/store指令有天然的省电优势。不用频繁从内存调数据。
X86是3指令汇编 说白了每条指令都得玩内存 ...


x86不需要每条指令都要读内存吧,而且主流的库基本上都为x86缓存特性做了优化了。

arm的load/store有专项指令ldr str而已,x86都叫做mov而已,本质没区别

其实你要是熟悉编译器,你会发现x86,同样一个mov,其实对应的字节编码是不一样的,对于cpu其实是不同的指令,其实ldr str在x86内是存在的,只是没有专门给它们命名而已,为了可读性,都叫做mov。同样,什么jmp,sub,add之类都一样的。

其实arm也有同样的问题,其实一个mov add之类,对于cpu也是有很多不同的指令的,有一本arm编码规范,看一下就知道了。

主要是操作数可能是8位,16位,32位,或者绝对地址,相对地址啥啥的,对于cpu都是有区别的。都叫做mov,其实不是一个东西而已。

比如
ldr r0,0xabcd
mov eax,dword ptr[0xabcd]

功能上没区别

mov r0,r1
mov eax,ebx

也没区别,这个没有内存操作的

况且arm还有

ldr r0,=0xabcd这种伪指令,跟x86,mov eax,0xabcd是一样的,这个也没有内存操作

x86由于指令太复杂,专有的指令解码器比较浪费电量而已,但是标准a15的整数运算管线增加到三条,浮点增加到两条,其实解码模块占据的比例也就那么回事了。

arm最省电的还是单运算管线的那些东西,armv11之前的那些玩意,x86再省电,也不做不到arm这个级别的吧。

作者: largewc    时间: 2013-3-12 13:45
芦鹏Coolboy 发表于 2013-3-12 13:23
ARM 的load/store指令有天然的省电优势。不用频繁从内存调数据。
X86是3指令汇编 说白了每条指令都得玩内存 ...

arm最恶心的是最早的标准居然没有32位赋值,直到thumb-2才支持,两条指令做一个32位赋值,而且见鬼的安卓ndk默认编译都不是thumb-2,而是thumb

用标准的arm指令和thumb指令赋值一个0x89ABCDEF,需要代码跟内存混写的方式才行,arm性能能高才见鬼了。之前写过这个代码范例了,这里就不写了,无论是微软的老的wm编译出来的,还是xcode,还是ndk,不用thumb-2编译出来都是一样的,效率很低。


很大的三级缓存和很大的内存带宽还是因为core长流水线的问题,预测错误带来的内存无效读取很多,必须用足够的缓存和带宽才能弥补。

a15流水线也不短了,不出意外内存对性能影响一样很高……
作者: 芦鹏Coolboy    时间: 2013-3-12 13:50
本帖最后由 芦鹏Coolboy 于 2013-3-12 13:53 编辑
largewc 发表于 2013-3-12 13:37
x86不需要每条指令都要读内存吧,而且主流的库基本上都为x86缓存特性做了优化了。

arm的load/store有专 ...

呵呵 遇到懂得了。
现在X86问题是大量编译不良得代码。
假如每个开发者都用inter的优化编译器的话可能会省电的多。
而ARM则从CPU体系上搞定了这个问题。
有个统计是大概只有%20-30的PC软件用inter的编译器优化过。
其他基本是MSDEV,GCC(没用编译优化)。其实这也正常在程序正常能跑的情况下谁会去花时间优化?闲的呵呵

作者: largewc    时间: 2013-3-12 13:58
本帖最后由 largewc 于 2013-3-12 15:13 编辑
芦鹏Coolboy 发表于 2013-3-12 13:50
呵呵 遇到懂得了。
现在X86问题是大量编译不良得代码。
假如每个开发者都用inter的优化编译器的话可能会 ...


ms编译器优化的程度跟intel差距并不大,没有当初vc6时代,intel编译器跟MS自己的编译器的差距。

arm优化其实也是有意义的,比如说全局变量尽量少用,优化成局部变量。

全局变量因为访问了另外一块内存地址,会造成缓存瞬间切换读取很多无用的内存,这跟arm x86之类没关系。

arm现在优化的少,个人感觉是arm的编译器太渣了,优化水平还在儿童级别,不然的话,水果也不会自己抛开gcc,自己投资编译器给xcode用了。
作者: 芦鹏Coolboy    时间: 2013-3-12 14:01
largewc 发表于 2013-3-12 13:58
ms编译器优化的程度跟intel差距并不大

arm优化其实也是有意义的,比如说全局变量尽量少用,优化成局部 ...

我要说的意思是大量PC软件开发者连编译优化都不会用。
用VS开个工程写完代码,直接编译就发布了。这是硬伤没救的。
而ARM体系上就适合这种代码,虽然慢但省电。
作者: largewc    时间: 2013-3-12 14:04
芦鹏Coolboy 发表于 2013-3-12 14:01
我要说的意思是大量PC软件开发者连编译优化都不会用。
用VS开个工程写完代码,直接编译就发布了。这是硬 ...

vs好歹你得编译一个release版本吧,这个不做修改,默认编译的优化就够了,没必要特别开深度优化,可能会造成代码错误。

debug版本发布不了的,依赖库问题解决不了。


这个只是影响性能,跟耗电量没任何关系。
作者: 芦鹏Coolboy    时间: 2013-3-12 14:10
本帖最后由 芦鹏Coolboy 于 2013-3-12 14:12 编辑
largewc 发表于 2013-3-12 14:04
vs好歹你得编译一个release版本吧,这个不做修改,默认编译的优化就够了,没必要特别开深度优化,可能会造 ...

影响性能怎么和耗电量没关系。
假如1W行热代码
优化编译为10万行汇编
不优化编译为20万行汇编
假设某CPU有闲置节能机制 运行完就降频等待了。
那很容易得出结论 优化编译的程序执行时间为1的话 不优化编译的程序执行时间为2
怎么会不节能呢。假如此代码周期性重复执行比如某游戏。那基本可以确定优化编译比不优化编译节能一半。

作者: Prescott    时间: 2013-3-12 14:17
芦鹏Coolboy 发表于 2013-3-12 13:23
ARM 的load/store指令有天然的省电优势。不用频繁从内存调数据。
X86是3指令汇编 说白了每条指令都得玩内存 ...

扯蛋,随便一条LEA指令,就够ARM写好几条指令的。

要计算就要访问内存,x86访问内存指令比例高,只不过是x86一条指令当ARM好几条用而已。
作者: largewc    时间: 2013-3-12 14:22
芦鹏Coolboy 发表于 2013-3-12 14:10
影响性能怎么和耗电量没关系。
假如1W行热代码
优化编译为10万行汇编

你说指令效率,arm比x86低多了,同样长度的代码x86比arm能干的事情多很多倍,性能也高多了。


这个也不是啥新闻了,x86耗电,主要还是那个解码模块,但是它另外的好处就是高性能。

所以才会有顺序双发的atom性能好于乱序双发的arm,很多时候,atom ht以后的单运算单元可以跟arm单核两个运算单元抗衡性能啊,功耗水平也差不多。

x86在绝对性能上是没啥敌手的,它当初设计就是为这个来的。

至于低功耗,还是那个,arm非要增加运算管线,进入高性能之争,这玩意会消耗掉arm所有的低功耗优点的。
作者: Tempestglen    时间: 2013-3-12 14:25
提示: 作者被禁止或删除 内容自动屏蔽
作者: largewc    时间: 2013-3-12 14:29
Tempestglen 发表于 2013-3-12 14:25
arm也可以玩超线程。

顺序双发的A8和atom ipc差不多,不要神化x86。

好吧你说差不多就差不多吧,我们自己写程序测试的都是假的。

不想跟你争了。
作者: largewc    时间: 2013-3-12 14:46
本帖最后由 largewc 于 2013-3-12 15:53 编辑
芦鹏Coolboy 发表于 2013-3-12 13:50
呵呵 遇到懂得了。
现在X86问题是大量编译不良得代码。
假如每个开发者都用inter的优化编译器的话可能会 ...


其实arm优化跟x86有啥区别啊,比如说你要为arm a7 a8优化,顺序双发的cpu,你仍然要给代码做乱序优化,否则性能就很差。

简单的例子

ldr r3,=333

ldr r0,=123
add r0,r0,r3

ldr r1,=321
add r1,r1,r3

对于双管线的a7 a8来说,ldr r0,=123跟add r0,r0,r3都用了寄存器r0,add运算必须要等r0赋值以后才能继续,那么一条管线就阻塞了,所以做一下乱序

ldr r3,=333

ldr r0,=123
ldr r1,=321

add r0,r0,r3
add r1,r1,r3

上面的修改,就可以同时运行两条指令,也不会互相冲突,就能完美适应顺序双发的cpu了。
作者: frankincense    时间: 2013-3-12 14:57
Tempestglen 发表于 2013-3-12 14:25
arm也可以玩超线程。

顺序双发的A8和atom ipc差不多,不要神化x86。

你的意思是,ARM从顺序双发的A8改为乱序双发的A9,IPC反而下降了,然后再改为乱序三发的A15也只比A8好那么一点,这样么?
作者: 碎梦刀    时间: 2013-3-12 15:42
x86做移动芯片真不行?为Intel“平反”
http://news.mydrivers.com/1/257/257076.htm

T神说的论文就是这篇报道里的内容吧。能在IEEE高性能计算机架构国际研讨会上发表的研究报告应该具有一定的份量和严谨性。
一直以来PCI里的争论大都具有一定的技术含量,当年酷睿出世时的论辩,近来ARM与intel孰优孰劣的争论。
只是唯心论者是永远也辩不倒的,与其谩骂不如静看arm与intel未来1-5年间的发展。
作者: Tempestglen    时间: 2013-3-12 16:44
提示: 作者被禁止或删除 内容自动屏蔽
作者: YsMilan    时间: 2013-3-12 16:49
Tempestglen 发表于 2013-3-12 16:44
单线程ipc,A8接近于A9,A9等于atom。

atom不就是借着当年dec的超线程技术实现了1c2t来对抗A9的2c2t ...

T神不是神喻过我等,超线程无用么?
作者: YsMilan    时间: 2013-3-12 16:56
[attach]2191304[/attach]
x86上叫放弃半壁江山
Arm上就叫性能立马暴涨...
作者: the_god_of_pig    时间: 2013-3-12 16:57
Tempestglen 发表于 2013-3-12 16:44
单线程ipc,A8接近于A9,A9等于atom。

atom不就是借着当年dec的超线程技术实现了1c2t来对抗A9的2c2t ...

发什么梦,atom是顺序的所以超线程才能提升大,Core是乱序HT也就提升10%,你要YY ARM上SMT只能等A57的儿子,手机上ARM能不能活到那个时候都是问题

作者: YsMilan    时间: 2013-3-12 17:01
等A15出来.
等A57出来..
等xxG的Axx出来...
等丹佛出来....
等解决了chrome的优化问题...
等xx工艺出来...
最新:等Arm启用超线程
作者: foolme    时间: 2013-3-12 17:45
largewc 发表于 2013-3-12 13:45
arm最恶心的是最早的标准居然没有32位赋值,直到thumb-2才支持,两条指令做一个32位赋值,而且见鬼的安卓 ...

今天看到CM10.1的nightly开始默认启用armeabi-v7a了,应该是默认启用了neon和thumb-2
另外,arm的指令集系统不是有两套吗?为什么一定要用thumb子集呢?
完全使用arm指令集不就行了吗?
毕竟thumb指令集是针对指令密度要求比较高的嵌入式环境的
应该ios、android、wp8之类的系统不需要考虑用thumb指令集吧。

PS:本人不会汇编,arm架构也不清楚,只是外行的看法。

作者: largewc    时间: 2013-3-12 18:14
foolme 发表于 2013-3-12 17:45
今天看到CM10.1的nightly开始默认启用armeabi-v7a了,应该是默认启用了neon和thumb-2
另外,arm的指令集 ...

标准arm指令效率更低,再写一遍吧,标准arm,比如说int a = 12345678;

x86一条mov a,0小2345678的事情

编译的结果一定是

:start
ldr r0,[+0];//取得memroy偏移的内容
b next      //跳下去继续执行
:memery
0x12345678
:next


因为arm或者thumb-2都是32位固定长度指令,所以肯定无法一条指令进行足够的32bit赋值,至少需要两条,而thumb-2就是有专门的两个,一个是给高16bit赋值,一个是给地16bit赋值,两条可以进行一个赋值。

对于c++原生开发来说,是必要的,ios从4.0开始,强制了thumb-2,其实就是iphone 3gs以后才能升级,之前不允许了。xcode默认也是thumb-2

wp来说,也是如此,thumb-2是默认选项,没有疑问。

安卓由于兼容性考虑,老的armv11之类还有在用的吧,所以ndk默认是thumb

这跟系统没关系,是每一个原生软件的问题,比如说游戏,播放器,导航之类,都是原生程序。
作者: largewc    时间: 2013-3-12 18:22
还有的事,标准的arm,比如说堆栈内临时变量,一般采用堆栈寄存器加偏移地址来实现的。
void test()
{
...
..

int b = i;//这样的访问,b假如代码很长,临时变量很多,或者有一个数组的临时变量,超过了一个长度(貌似是4000字节左右的,具体忘了)
}

对于x86,那就是mov eax,[ebp+0x很长的偏移;假设

而arm则不行,因为ldr r0,r15,0x很长偏移;这里的很长偏移超过一定长度,超过了32bit指令的描述范围,单挑指令就不行了

所以结果就成了,刚才那个32bit赋值,付给了r1之类,然后再用ldr r0,r0,r1来实现。


thumb-2的话,则略好点,首先是thumb-2版本的ldr宽度变宽了,支持一些压缩数据算法,其次就是即使宽度不够了,需要的指令数量也远远少于arm本身指令。


thumb-2以后,arm的性能才稍微可以看看,标准arm就算了。

安卓其实早该统一下标准淘汰老的armv11之类的cpu算了。

作者: Prescott    时间: 2013-3-12 18:25
foolme 发表于 2013-3-12 17:45
今天看到CM10.1的nightly开始默认启用armeabi-v7a了,应该是默认启用了neon和thumb-2
另外,arm的指令集 ...

ARM指令集有时候性能还不如Thumb-2。尤其是当ARM处理器的内存带宽有限的时候。
编译成Thumb-2指令集通常会减少30%左右的可执行文件大小,在内存带宽很小,缓存也很小的时候,反而提高性能(减少了从内存读取指令的大小,减少了指令占用的缓存大小)。

现在的高性能ARM,带宽也不算低了,应该影响不大了

不过Thumb-2真是讽刺,鼓吹定长RISC指令集的ARM,居然搞出一个变长的指令集出来。

作者: largewc    时间: 2013-3-12 18:33
Prescott 发表于 2013-3-12 18:25
ARM指令集有时候性能还不如Thumb-2。尤其是当ARM处理器的内存带宽有限的时候。
编译成Thumb-2指令集通常 ...

thumb-2也是定长的啊,汗

thumb-2主要是支持了一些压缩数据之类,增加了不少专有指令,弥补了arm本身的不足。
作者: Prescott    时间: 2013-3-12 18:35
largewc 发表于 2013-3-12 18:14
标准arm指令效率更低,再写一遍吧,标准arm,比如说int a = 12345678;

x86一条mov a,0小2345678的事情 ...

hehe,基本上就是因为RISC非要定长,所以一条指令只有32bit长,操作码寄存器占掉大部分,结果就是想写个稍微大点的常量到指令里就不行,哈哈。

给寄存器赋常量值,跳转,偏移量寻址等等,都受限
作者: Prescott    时间: 2013-3-12 18:37
本帖最后由 Prescott 于 2013-3-12 18:42 编辑
largewc 发表于 2013-3-12 18:33
thumb-2也是定长的啊,汗

thumb-2主要是支持了一些压缩数据之类,增加了不少专有指令,弥补了arm本身的 ...

Thumb-2 is an enhancement to the 16-bit Thumb instruction set. It adds 32-bit instructions that can be freely intermixed with 16-bit instructions in a program. The additional 32-bit instructions enable Thumb-2 to cover the functionality of the ARM instruction set. The 32-bit instructions enable Thumb-2 to combine the code density of earlier versions of Thumb, with performance of the ARM instruction.
基本上,thumb-2比thumb增强的部分就是可以16bit指令和32bit指令混写。
原来的thumb指令只能是16位的,处理器需要一条指令(BX/BLX)在32bit的ARM模式和16bit的thumb模式之间切换,切换的开销倒不是很大,不到10个cycle。但是通常没人这么干过(碰巧我这么干过,连OS都要改才能跑

作者: largewc    时间: 2013-3-12 19:41
Prescott 发表于 2013-3-12 18:37
Thumb-2 is an enhancement to the 16-bit Thumb instruction set. It adds 32-bit instructions that ca ...

arm跟thumb切换吧,必须代码地址偏移加一才能正常。

thumb-2比标准arm优化了些东西,应该算是cisc化增强吧,当然不排除为了弥补arm先天问题,继续增加thumb-3指令,不过整个产业链是否可以接受折腾就不知道了。

我自己有一个语言编译器,jit搞过x86和arm,对arm较熟悉,arm其实性能感觉比当初奔三啥的强,很大的因素就是gpu,现在的操作系统对gpu优化到位了,当初p3是靠cpu傻跑的
作者: foolme    时间: 2013-3-12 20:46
largewc 发表于 2013-3-12 18:14
标准arm指令效率更低,再写一遍吧,标准arm,比如说int a = 12345678;

x86一条mov a,0小2345678的事情 ...

专门查了一下C语言的标准。因为C语言通常采用一段地址专门储存常量,所以情况可能有些出入
以你的例子,int a=0x12345678
如果是C编译器生成的指令的话,应该是
ARM:
mov r1,=addr of 0x12345678
ldr r0,[r1]
x86:
mov EBX, addr pf 0x12345678
mov EAX, [EBX]
因此两者开销相差不多。
就算是如同你的例子,我也没觉得有什么问题,
原因有几点:
1.内存是8位宽度为基础的。对于CPU来说无论是x86还是arm,数据都还是一个个的读到CPU里的。如果说什么预取技术之类的那么大家都一样有。而且以arm来说由于指令对齐。预取效率说不定更高。
2.对于CPU来说,实现一个操作不是看汇编的,而是看机器码的,并不是说汇编指令少就一定执行的快。以你的例子我认为机器码所占空间相差不大。x86在这方面只不过占了阅读和书写的便宜。
3。现在除了一些特定场合外,应该没有什么必要用汇编来写程序了吧。实际上有研究表明手工优化的汇编并不比C语言编译出来的代码执行效率更优秀。
另外CM10.1今天开始就是默认用armeabi-v7a来编译系统,只不过仍然保留armeabi的运行库。
希望以后的程序都采用这个标准吧。

总而言之,我认为指令集的差别并不会太影响cpu性能。差别主要在硬件实现上

一家之言,请多指教
作者: largewc    时间: 2013-3-12 20:58
foolme 发表于 2013-3-12 20:46
专门查了一下C语言的标准。因为C语言通常采用一段地址专门储存常量,所以情况可能有些出入
以你的例子, ...

我跟你说,mov r1,=addr of 0x12345678这个指令不成立,因为arm就是32bit的,光0x12345678就有32bit,指令码要放在哪里?你去找编译器写段试试,然后反编译看看就知道了。


你以为是动长的x86?mov eax,0x12345678可以用六个字节来表示?

定长的arm指令,操作数受限的问题,有一堆麻烦事,夺取看看再说吧。


长度怎么不重要,你的解码,运行都是需要周期的。还是那个东西,多写写汇编就懂了。


指令怎么不重要,很简单的问题a7 a15有除法指令,a8 a9没有的,你去测试一下真机除法的效率吧,测试一下你再说结论吧。


至于汇编优化的问题,这个意思就是,大部分人对cpu的理解来看,你写还不如编译器优化懂得多,因为你不理解cpu原理的话,很可能你写出来的代码比原来的代码效率还低。



最简单的,说个难听的,02年一家老牌的游戏公司,在做2d alpha blend的时候,当时是没有gpu加速的,他们采用的办法居然是把加法改成了查表……

好吧,内存操作要浪费的时间远比cpu运算高多了。
作者: largewc    时间: 2013-3-12 21:08
本帖最后由 largewc 于 2013-3-12 21:16 编辑

而且你的这段代码的意思相当于 int a = *(int*)0x12345678;

这个代码用x86就是mov eax,dword ptr[0x12345678];一条指令

用arm,最优化的thumb-2,也需要
movw r1,0x1234;
movt r1,0x5678;
ldr r0,r1
三条指令,你的那个汇编指令mov r1,=0x12345678在编译过程中,翻译成thumb-2机器码结果就是我写的这段代码。arm编译器支持部分伪代码,就是为了让你看起来方便,合并了一些指令,但是实质是很多条。

如果用arm标准指令最低是四条,如果指令集真的没用的话,thumb-2,为什么要加入movw和movt来优化32位赋值呢,而且它仍然比不了动长的x86效率。


复杂指令的特点就是,x86那个指令是一个专用指令,它优化了效率。


-----------------------------
我说的就是机器码,其实无论是x86,还是arm,光一个mov,其实有很多不同的机器码的,机器码的数量比你看到的汇编指令多太多了,x86的特点就是足够的多,它考虑了各种情况,所以效率是最高的,但是编译器做起来也是最麻烦的,因为优化你要考虑太多的专有指令了。

arm虽然相对简单,但是thumb-2也增加了不少指令,不过它的效率仍然无法跟x86相比。

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

要说可读性,其实arm汇编读起来比x86简单太多了,x86编译器太复杂,代码可读性很差,更别说x86还有专门的代码混淆算法,因为变长指令通过非常规跳转可以让汇编代码完全不可被分析。

作者: largewc    时间: 2013-3-12 21:25
本帖最后由 largewc 于 2013-3-12 21:33 编辑
Prescott 发表于 2013-3-12 18:35
hehe,基本上就是因为RISC非要定长,所以一条指令只有32bit长,操作码寄存器占掉大部分,结果就是想写个稍 ...


是啊是啊,而且见鬼的arm很多指令都是三操作数的,也就是add r1,r2,r3这种格式
--------------------------
arm并且还有16个常规寄存器,也就是每个寄存器是4位的,add r1,r2,0x1234这样的话,除去指令码的16bit 两个寄存器的8 bit,还有标志位啥啥的2-3bit,留给操作数的往往只有5-7bit了,操作数最大不能超过127的太多了……
--------------------------
更正一下,查了一下资料,add之类的指令码占10bit 寄存器两个8 bit 标志位3bit,留给操作码有11bit,也就是最大不能超过2048,加上标志位的正负判定,也就是4096最大范围,这个是准确的。

如果操作数不够,就得拆成2b的mov r7,操作数啥啥的

怪不得arm需要16个寄存器,定长指令,如果寄存器不够拿来凑数的话,估计效率会坑死。

作者: Prescott    时间: 2013-3-12 21:27
foolme 发表于 2013-3-12 20:46
专门查了一下C语言的标准。因为C语言通常采用一段地址专门储存常量,所以情况可能有些出入
以你的例子, ...

mov r1,=addr of 0x12345678
ldr r0,[r1]

这个mov r1,=addr of 0x12345678还是回到了第一个问题,因为addr of var实际上也是个常量。
ARM可以这样干:
ldr    r0, [pc, offset],不过offset的范围只有4096
作者: foolme    时间: 2013-3-12 22:38
Prescott 发表于 2013-3-12 21:27
mov r1,=addr of 0x12345678
ldr r0,[r1]

就是这个意思,即间接寻址,addr of var是个常量,
但是编译后一般这个地址有可能是由一个基地址+变量组成。
我不太清楚arm的地址空间有多大,但是x86也有段地址+偏移量的寻址方法。arm难道没有吗?
有没有可能用一个指令完成地址加载呢。

如果说arm一定要用立即数的方式的话,就像largewc所写的
movw r0,0x1234
movt r0,0x5678
不就解决问题了?
实际代码长度是多少呢?和x86比起来呢?

另外 largewc
我的意思C编译器出来的机器码x86的机器码长度和arm有可能是一样的。
另外除法指令是有与没有的区别,当然很大,但是实现同样功能的指令集性能就相差不会太远吧?
arm官方的说法是thumb-2的性能是arm标准指令集的98%,实际上任何稍微差些的程序结构就会把这2%的性能给挥霍掉了。


作者: Tempestglen    时间: 2013-3-12 22:49
提示: 作者被禁止或删除 内容自动屏蔽
作者: largewc    时间: 2013-3-12 22:50
foolme 发表于 2013-3-12 22:38
就是这个意思,即间接寻址,addr of var是个常量,
但是编译后一般这个地址有可能是由一个基地址+变量组 ...

我说过了,是不一样的,arm每条指令32bit,实现你说的那个内存取值需要三条thumb-2指令,也就是12字节,如果是arm标准,则是四条指令,一共16个字节,而x86则是一条指令,6个字节,这个明白了吗?

偏移arm是支持的,但是就是我说的,你的堆栈内临时变量超过4096个字节,超过了arm 32bit的指令数部分,最少就需要8个字节,一共两条指令才能访问到一个临时变量,你明白了吗,而x86访问,根据长度,有2-6个字节不等的cpu指令,指令数不同,代码长度也不同,但是都是一条cpu指令,这个明白了吧。

x86的复杂指令是有道理的,它优先照顾了各种情况,照顾了性能,而arm和mips很多地方是没有特别指令的,所以需要多条指令去模拟,甚至最简单的32位赋值也是如此,这个够清楚了吧。
作者: Tempestglen    时间: 2013-3-12 22:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: koppie    时间: 2013-3-12 23:01
largewc 发表于 2013-3-12 13:37
x86不需要每条指令都要读内存吧,而且主流的库基本上都为x86缓存特性做了优化了。

arm的load/store有 ...

区别也就是x86指令翻译成RISC-like指令的额外开销了。看Sandy Bridge的decode单元的面积还是不下啊,虽说Sandy Bridge新引入的解码cache可以减少循环的时候的功耗
作者: koppie    时间: 2013-3-12 23:04
largewc 发表于 2013-3-12 13:45
arm最恶心的是最早的标准居然没有32位赋值,直到thumb-2才支持,两条指令做一个32位赋值,而且见鬼的安卓 ...

ARMv8普及了就好了吧

不过还是觉得MIPS64是最简洁的
作者: largewc    时间: 2013-3-12 23:08
koppie 发表于 2013-3-12 23:01
区别也就是x86指令翻译成RISC-like指令的额外开销了。看Sandy Bridge的decode单元的面积还是不下啊,虽说 ...

但是带来的额外好处就是性能仍然是非常高,这不是软件层能弥补的。

复杂指令就是一个双刃剑,好处是性能,坏处就是最低功耗搞不定

而且atom和amd都不是翻译risc的设计,x86可以为了性能,为每一个专有指令做专门的电路来优化,可以做到更低的功耗和更好的性能,代价就是研发成本更高。
作者: koppie    时间: 2013-3-12 23:10
芦鹏Coolboy 发表于 2013-3-12 13:50
呵呵 遇到懂得了。
现在X86问题是大量编译不良得代码。
假如每个开发者都用inter的优化编译器的话可能会 ...

但是Intel的compiler可能会出现新的架构跑得更快,旧的架构跑得却更慢的情况。或者在AMD的上面跑得不好呢。毕竟x86编译最后还是要把RISC类型指令按pattern匹配翻译回x86

不过记得有的程序在AMD处理器上跑,用AMD的编译器编译不如Intel编译器编译出来的代码快,真是奇葩了

我觉得这就是个圈,
编译:source code -> RISC-type intermediate -> 优化 -> x86指令
执行:x86 -> RISC -> 执行
要说一点性能损失都没有,我不信





作者: largewc    时间: 2013-3-12 23:12
koppie 发表于 2013-3-12 23:04
ARMv8普及了就好了吧

不过还是觉得MIPS64是最简洁的

ARMv8 的程序不能跑在老的arm cpu上的,估计就是出了,程序迎合的概率都很低,现在arm不是刚开始的那会了,不兼容的指令造成的安卓,ios,wp早期的系统更新换代,软件兼容问题,用户还可以一定程度上理解。

现在arm跟x86一样,历史包袱很大了,不是随便可以更新指令集了。
作者: koppie    时间: 2013-3-12 23:18
largewc 发表于 2013-3-12 13:58
ms编译器优化的程度跟intel差距并不大,没有当初vc6时代,intel编译器跟MS自己的编译器的差距。

arm ...

gcc编译器在X86上性能相对差,我觉得是由于开源社区能掌握的Intel/AMD处理器的架构资料有限,对其理解也肯定不如设计微架构的那些工程师。编译器的第一目标是编译正确,优化不能太aggressive,有些不能确定的东西就尽量不做。Intel的编译器有优势是因为x86需要深度优化

RISC的东西没有翻译来翻译去的过程,而且提出RISC就是为了简化编译器设计的,可优化的空间比x86更小。水果还是提供修改过的gcc的吧
作者: foolme    时间: 2013-3-12 23:22
largewc 发表于 2013-3-12 22:50
我说过了,是不一样的,arm每条指令32bit,实现你说的那个内存取值需要三条thumb-2指令,也就是12字节,如 ...

就象你所说的在某些情况下arm的指令会更长,不过这也是risc的特点。
但是你不能否认当操作数比较小的时候定长指令就有优势了,实际上程序里大部分都是比较小的操作数。

如果变量太多的话直接使用指针的话不行吗?用某个寄存器作为数据指针,直接访问内存?
我举出这些例子的意思是工具(指令集)可能不同,但是如何使用这些工具(编译器优化)才是最重要的,当然,比编译器优化intel是最牛的。

定长指令集和变长指令集各有各的好处,没有说谁更优胜。但是物理实现上变长指令集的实现就会更复杂一些。x86的复杂指令内部还不是一样要解码成定长的微代码,毕竟只有定长代码才能更好的适应执行管线。

作者: YsMilan    时间: 2013-3-12 23:33
Tempestglen 发表于 2013-3-12 22:55
A15等来了,2.3ghz arm等来了,big little,等来了。arm目前占据平板手机优势地位,不着急,等就等怕什么 ...

是啊是啊,干掉x86笔记本的特瓜2早就等来了
等anandtech功耗测试等来个火辣辣的数据
PK I7的大丹佛更是将要马上很快来了

作者: koppie    时间: 2013-3-12 23:35
largewc 发表于 2013-3-12 14:22
你说指令效率,arm比x86低多了,同样长度的代码x86比arm能干的事情多很多倍,性能也高多了。

没有很多倍那么夸张吧,一点几倍吧。ARM不是有Thumb-16么

我看,ISA上看ARM在高性能上是没什么问题的。最终还是取决于microarchitecture的具体实现。搞一个4-issue,乱序,SMT,speculative的架构, 塞同样的128ROB进去, 是可以是实现高性能的。

反过来看低功耗也是一样,跟ISA关系不大。Atom的内部指令和Sandy Bridge是非常不一样的,加上其他微架构的区别,导致二者的功耗比差不少。X86唯一的劣势就是译码的额外开销,以及编译器优化对微架构的高度依赖

作者: koppie    时间: 2013-3-12 23:35
largewc 发表于 2013-3-12 14:22
你说指令效率,arm比x86低多了,同样长度的代码x86比arm能干的事情多很多倍,性能也高多了。

没有很多倍那么夸张吧,一点几倍吧。ARM不是有Thumb-16么

我看,ISA上看ARM在高性能上是没什么问题的。最终还是取决于microarchitecture的具体实现。搞一个4-issue,乱序,SMT,speculative的架构, 塞同样的128ROB进去, 是可以是实现高性能的。

反过来看低功耗也是一样,跟ISA关系不大。Atom的内部指令和Sandy Bridge是非常不一样的,加上其他微架构的区别,导致二者的功耗比差不少。X86唯一的劣势就是译码的额外开销,以及编译器优化对微架构的高度依赖
作者: raini    时间: 2013-3-12 23:43
Tempestglen 发表于 2013-3-12 22:49
双核A15如果实现2c4t那就是性能暴涨,在那些能利用4t的程序上收获很大。
2c4t atom vs 2c2t a15

"2c4t atom放弃的是仅仅支持2t的程序,这种程序占据半壁江山,那种能支持4t的程序在数量上也是半壁江山。"
这SB弱智太监丢人现眼地还嫌不够?这么弱智的话都能说出来?
当然太监就是太监,因为没有嘛,还要说人家的也是没用的。
果然跟太监是一样一样的
作者: the_god_of_pig    时间: 2013-3-12 23:43
Tempestglen 发表于 2013-3-12 22:55
A15等来了,2.3ghz arm等来了,big little,等来了。arm目前占据平板手机优势地位,不着急,等就等怕什么 ...

等来的A15和big little是两坨S,2.3G A9一时还等不来,等来了也就是个过时烂货而已

作者: koppie    时间: 2013-3-12 23:45
largewc 发表于 2013-3-12 14:46
其实arm优化跟x86有啥区别啊,比如说你要为arm a7 a8优化,顺序双发的cpu,你仍然要给代码做乱序优化, ...

x86不一样的地方在于,编译的时候使用的IR中间格式,不一定就是处理器内部指令的格式(不同Intel处理器的内部micro ops甚至可能不同,例如Atom和i7)

编译器优化的基本方法大家都差不多,common subexpression啊,loop unrolling啊,local/global啊。关键是RISC的中间格式就是目标指令集,x86的中间格式是可以不同的(反正最后都要翻译回x86),这就造成了x86不同的编译器之间性能差距可能更大



作者: koppie    时间: 2013-3-12 23:47
Tempestglen 发表于 2013-3-12 16:44
单线程ipc,A8接近于A9,A9等于atom。

atom不就是借着当年dec的超线程技术实现了1c2t来对抗A9的2c2t ...

SMT功耗不可能不变的
作者: YsMilan    时间: 2013-3-12 23:47
Tempestglen 发表于 2013-3-12 22:49
双核A15如果实现2c4t那就是性能暴涨,在那些能利用4t的程序上收获很大。
2c4t atom vs 2c2t a15

仅仅支持2t的程序?能支持4t的程序?数量上半壁江山?
这个是本地球上的程序么???
T神啊,去发论文申请图灵奖吧,我实在是太看好你了
作者: koppie    时间: 2013-3-12 23:52
largewc 发表于 2013-3-12 18:22
还有的事,标准的arm,比如说堆栈内临时变量,一般采用堆栈寄存器加偏移地址来实现的。
void test()
{

displacement超过32bit指令描述的范围,那就用jump了吧
作者: YsMilan    时间: 2013-3-12 23:57
本帖最后由 YsMilan 于 2013-3-12 23:58 编辑
Tempestglen 发表于 2013-3-12 22:49
双核A15如果实现2c4t那就是性能暴涨,在那些能利用4t的程序上收获很大。
2c4t atom vs 2c2t a15

来,T神,一个开了IE的Win7任务管理器截图
[attach]2191841[/attach]
82进程,按神之教诲,半壁江山的话...
支持2t的41,2X41=82线程
支持4t也是41,4X41=164线程
82+164=246线程
等等!怎么会是1308个线程!一定是微软搞的花招!T神面前,一切花招都无所遁形!!!
图灵奖在等着你哪,T神!


作者: koppie    时间: 2013-3-13 00:08
largewc 发表于 2013-3-12 23:08
但是带来的额外好处就是性能仍然是非常高,这不是软件层能弥补的。

复杂指令就是一个双刃剑,好处是性 ...

Atom翻译后的内部指令是介于CISC和RISC类型之间的,它允许一条指令既做load/store又搞ALU运算。但是AMD的处理器依然是翻译RISC的,当然他们的macro-ops和micro-ops和Intel的意义不一样。

X86也没有怎么对专有指令做专门的电路优化,因为那样做就不能跑高频了。对每一个专有指令做专门的电路是传统的CISC思路,早已经被业界抛弃了(90年代),因为没法搞pipeline和superscalar。


作者: FENG950    时间: 2013-3-13 00:12
koppie 发表于 2013-3-12 23:18
gcc编译器在X86上性能相对差,我觉得是由于开源社区能掌握的Intel/AMD处理器的架构资料有限,对其理解也肯 ...

RISC更依赖编译器,它的一个思想就是软件干多点,硬件干少点。
作者: FENG950    时间: 2013-3-13 00:14
koppie 发表于 2013-3-12 23:45
x86不一样的地方在于,编译的时候使用的IR中间格式,不一定就是处理器内部指令的格式(不同Intel处理器的 ...

编译器针对的是机器代码,跟处理器内部机器代码怎么运作没有关系,如果有,这个封装设计的就太失败了。
作者: koppie    时间: 2013-3-13 00:17
本帖最后由 koppie 于 2013-3-13 00:40 编辑
FENG950 发表于 2013-3-13 00:12
RISC更依赖编译器,它的一个思想就是软件干多点,硬件干少点。

但是好的编译器之间的水平不会有很大差别。话说回来,80年代开始的性能飞跃不就是基于RISC的pipeline和编译器技术的结合么
自从90年代开始,x86处理器的内部基于RISC,x86是软件也得多干点(编译要多一步),硬件也得多干点(翻译指令)

作者: koppie    时间: 2013-3-13 00:20
FENG950 发表于 2013-3-13 00:14
编译器针对的是机器代码,跟处理器内部机器代码怎么运作没有关系,如果有,这个封装设计的就太失败了。

但是在X86上,它就是有关系的。即使在MIPS上,性能也是有关系的

所谓没关系,只是最后生成的binary不依赖于微架构的具体实现。中间的优化是必须要考虑架构的

作者: koppie    时间: 2013-3-13 00:35
largewc 发表于 2013-3-12 23:12
ARMv8 的程序不能跑在老的arm cpu上的,估计就是出了,程序迎合的概率都很低,现在arm不是刚开始的那会了 ...

向后兼容就可以了,X86-64不也是这么过来的
作者: largewc    时间: 2013-3-13 01:19
koppie 发表于 2013-3-13 00:35
向后兼容就可以了,X86-64不也是这么过来的

64bit其实在x86普及度实际并不高,绝大多数程序仍然是32位的。
arm会面临一摸一样的问题。

我说的很多倍,放在mov上不适合,但是类似交换两个寄存器值XCHG,字符串比较指令CMPSB,还有内存拷贝,高低位互换,整数转浮点等等一大堆专用加速指令,这些指令用不用可能不止几倍的关系,几十倍的性能差都是有的。无论你如何在代码层优化也是没用的。
作者: largewc    时间: 2013-3-13 02:30
本帖最后由 largewc 于 2013-3-13 02:32 编辑
koppie 发表于 2013-3-12 23:10
但是Intel的compiler可能会出现新的架构跑得更快,旧的架构跑得却更慢的情况。或者在AMD的上面跑得不好呢 ...


在我看来,x86复杂指令是包含了所有arm的那些简单指令的,它只是额外的复杂指令更多而已。

你这个图有一个极其大的悖论:

source core->risc这一步是必须的吗,我怎么看这个都不是必须的

很显然sourcode -> x86会更好一些,也简单许多,为什么要到risc这一步?

如果编译需要risc,执行也需要risc,而且中间有损失的话

-------------------------------------------------
那么为什么要x86这一步呢?本身x86是包含了risc的所有指令的

看不出arm有比x86更底层的指令是x86没有的,所有的x86复杂指令,都可以用简单指令模拟的,那么x86自己直接用简单指令模拟就行了


显然这是不行的,性能是不够的,最简单的movxx ,rep movxx这些系列指令,你可以跟arm完全一样,用循环来模拟,你可以试试,你能cpu多条简单指令模拟到消耗时间只有x86专用复杂指令的1.x倍,都不需要你做到性能更好,甚至2倍的差距以内都可以,你可以贴出来让我学习一下。


cisc的risc化绝不是简单的模拟了几条指令而已,复杂指令即使用risc的方式,也肯定有更深度的性能因素和优化方案。

其实这个悖论很好说明,如果x86的复杂指令更消耗性能,编译器直接去掉复杂指令就行了,这个没啥难度吧,可以下降复杂度到arm一个级别,只用x86自身的原始指令集,对于x86根本不用修改构架的。
作者: largewc    时间: 2013-3-13 02:36
我自己的编译器就不是你的那个设计的,我的做法就是直接x86化,如果arm对应没有专有指令,很简单,用简单指令模拟就好了,为什么一定要risc化呢,它有什么必然的好处?

当然优化幅度没有vc那么强硬,不过对于脚本逻辑级别,能跑机器指令,性能已经大幅度提升了。
作者: koppie    时间: 2013-3-13 07:23
本帖最后由 koppie 于 2013-3-13 07:25 编辑
largewc 发表于 2013-3-13 02:30
在我看来,x86复杂指令是包含了所有arm的那些简单指令的,它只是额外的复杂指令更多而已。

你这个图 ...

XD, 建议你读一下Dave Patterson(提出RISC这个词的人,Berkeley CS Chair,同时也是RAID的发明者)的书的辅助资料Section 2.15 Compiling C and Interpreting Java

http://www.elsevierdirect.com/co ... 01/CD_ROM_Files.zip

编译产生的IR(intermediate representation)是类似于MIPS风格的,只不过假设寄存器数量无穷。为什么不直接生成x86代码?因为很多X86指令的执行时间不可预测,例如ALU操作可以直接读写内存,内存的latency到底是多少个cycle,不同的环境下很难预测(在L1 cache中,在L2 cache中,在内存中,内存带宽的竞争,等等)。那么编译器又如何分配registers,每个指令的时间难以预测,他们占用的寄存器在多大的时间窗口之内不能被使用? 另外,你如何做code motion, 如何针对pipeline进行优化,如何优化branch和loop?指令系统越复杂,优化起来就越难。所以X86的编译也都是基于IR,最后阶段再特殊处理回归成x86以保持二进制兼容

从处理器设计的角度讲,现在的处理器的高性能很大程度依赖于pipeline(提高频率)。RISC的好处就在于所有的指令都可以用同一条若干级的pipeline经济高效地实现。除了load/store指令之外,其它指令的cycle数都是确定的 (store一般写入buffer,所以也是确定的)。这样设计pipeline就容易多了,进一步的什么bypassing啊乱序啊,multi-issue啊,分支预测啊,speculation啊才能用。直接设计一条x86能用的高效pipeline是不可想象的。所以从奔腾开始的处理器,都是先把x86指令翻译成内部的RISC类型指令,然后放到pipeline上去跑。

x86的原始指令集就是复杂的。你能要求一个X86编译器不生成memory-register类型的操作?而且即使最简单的那些指令,也不都是定长的,解码器还是不那么简单。RISC的一个特点就是指令长度固定。
作者: huangpobu    时间: 2013-3-13 07:50
lz20062336 发表于 2013-3-10 16:35
一篇会议论文,水平不高,也不一定很严谨。

HPCA是计算机体系结构领域的顶尖级学术会议之一。整个中国大陆都没发过几篇。

会议论文不绝对等于水平低,CS\EE领域里多少影响深远的工作都是在这种会议上发表的。

我已经下载了这篇文章,具体怎么样要读过才知道。
作者: huangpobu    时间: 2013-3-13 07:51
Prescott 发表于 2013-3-10 20:00
我一直说的就是这个啊,可惜T神不信。
至于敢和Intel拼微架构设计、制造工艺、编译器优化三项全能的公司, ...

确实,Intel自己的编译器也很厉害,看了一下测试结果远超Visual Studio 2010
作者: huangpobu    时间: 2013-3-13 08:32
koppie 发表于 2013-3-13 07:23
XD, 建议你读一下Dave Patterson(提出RISC这个词的人,Berkeley CS Chair,同时也是RAID的发明者)的书的 ...

同意,ISA会影响到编译器优化能力。

x86的通用寄存器太少编译器优化起来就放不开手脚。
作者: huangpobu    时间: 2013-3-13 08:42
Prescott 发表于 2013-3-12 14:17
扯蛋,随便一条LEA指令,就够ARM写好几条指令的。

要计算就要访问内存,x86访问内存指令比例高,只不过 ...

还有一个原因应该是寄存器不够用,很多变量要换回内存,计算时再换回来。
作者: largewc    时间: 2013-3-13 10:45
本帖最后由 largewc 于 2013-3-13 11:40 编辑
huangpobu 发表于 2013-3-13 08:32
同意,ISA会影响到编译器优化能力。

x86的通用寄存器太少编译器优化起来就放不开手脚。


通用寄存器少,只是对于risc的cpu有影响,对于cisc的cpu,几乎没有任何影响。

x86早就解决了这个问题了,很简单,因为x86有指令解码模块,所以x86内部的能够完全高效使用到一次缓存,实际上x86根本不用关心寄存器有多少,哪怕是回到图灵机,简单的push和pop,x86的效率都足够的高。

arm是把r0-r3作为参数传递寄存器,首先x86也可以做到同样的优化,把eax,ebx,ecx,edx也当作参数寄存器,当然这个优化对于现代的x86,是没有多大的意义的。

实际上做一个push操作,函数的参数和最近的堆栈,都被cpu缓存所记载,然后x86的指令解码模块会把内存操作全部映射成缓存操作的,实际上也就是寄存器同级别的操作,是根本没有额外消耗的。


给你写个代码证明一下



__declspec( naked )
void simpleTest1()
{
        __asm
        {
                add eax,ebx;
                add eax,ecx;
                add eax,edx;
                ret;
        }
}

__declspec( naked )
void simpleTest2()
{
        __asm
        {
                mov eax,dword ptr[esp+0x10];
                add eax,dword ptr[esp+0x0C];
                add eax,dword ptr[esp+0x08];
                add eax,dword ptr[esp+0x04];
                ret;
        }
}
void CUCSampleNETDlg::OnBnClickedOk()
{
        ucDWORD dwStartReg = ucTimer::GetTime();
        for (int i=0;i<100000000;i++)        
        {
                __asm
                {
                        mov eax,1;
                        mov ebx,2;
                        mov ecx,3;
                        mov edx,4;
                        call simpleTest1;
                        add esp,0;
                }
        }
        ucDWORD dwDisReg = ucTimer::GetTime() - dwStartReg;

        ucDWORD dwStartPush = ucTimer::GetTime();
        for (int i=0;i<100000000;i++)        
        {
                __asm
                {
                        push 4;
                        push 3;
                        push 2;
                        push 1;
                        call simpleTest2;
                        add esp,0x10;
                }
        }
}
simpletest两个版本,都是调用简单的函数,计算四个参数累加结果,然后返回给eax,做一个返回值的操作。一个是寄存器做参数的版本,一个是push用内存传递的结果。

第二种方式只用了eax这一个通用寄存器,这个够少了吧。

都跑一亿次,在我的一代i7上,寄存器的消耗是309毫秒,push和内存操作的消耗是317毫秒,实际上根本是一个级别的,寄存器数量对于x86性能影响是早期的x86了。

上面push带来的更高消耗,很大的程度上是因为第二种方法,多了一个mov eax,dowrd ptr[esp+0x10]一条指令而已,不论你代码优化成寄存器还是内存读写,消耗周期是一样的。


实际上,x86这样的好处就是,编译器根本不用做优化,附近计算的压栈出栈内存操作根本不需要优化成寄存器操作,反而不需要跟arm一样优化。

作者: largewc    时间: 2013-3-13 10:47
huangpobu 发表于 2013-3-13 08:42
还有一个原因应该是寄存器不够用,很多变量要换回内存,计算时再换回来。

实际上超过四个参数的函数,反而arm会大幅度下降性能,而x86完全没事情。

x86的指令解码模块不是摆在那里供观赏的。
作者: largewc    时间: 2013-3-13 10:50
koppie 发表于 2013-3-13 07:23
XD, 建议你读一下Dave Patterson(提出RISC这个词的人,Berkeley CS Chair,同时也是RAID的发明者)的书的 ...

我觉得这个对于早期的顺序执行的cpu影响更大吧,对于乱序执行的cpu,单指令周期无法预期,实际上并没有太大问题的,因为不同pipeline根本不会等待上一个执行结束。

还是那个问题,从x86编译器发展来看,cisc并没有risc化,如果risc既编程简单,又效率更高,其实x86可以完全risc化,因为复杂指令是包含了所有的简单指令的,只是你可以选择放弃复杂执行来做编译器而已。

但是实际上并不是,而是所有的编译器反而对复杂指令的使用都加深了,从而提高了性能。
作者: largewc    时间: 2013-3-13 11:00
koppie 发表于 2013-3-13 07:23
XD, 建议你读一下Dave Patterson(提出RISC这个词的人,Berkeley CS Chair,同时也是RAID的发明者)的书的 ...

不过还是谢谢你,我找时间看看这本书吧,最近还是很忙,我是无聊的代码测试分子,喜欢自己测试来看结果,哈哈。

我说的是,都是从我的角度来看,得出来的结论而已,如果真的有新的东西,我也非常感谢,能够学到东西。
作者: koppie    时间: 2013-3-13 11:09
本帖最后由 koppie 于 2013-3-13 11:10 编辑
largewc 发表于 2013-3-13 10:50
我觉得这个对于早期的顺序执行的cpu影响更大吧,对于乱序执行的cpu,单指令周期无法预期,实际上并没有太 ...

乱序执行也是有个窗口的,Sandy Bridge也就才100多个。如果你的memory cycle超过100(缓存不命中的话,就几百了),还是会stall的

x86如果只取简单的指令以及addressing modes,16个通用寄存器是不够用的(load/store型的ISA一般都是32或以上),也并不能包含所有简单指令。ISA最开始就定成这样子,你现在没法加的,加了就不能保持向后兼容。所以你必须用memory-register addressing。而且即使取出这些简单指令,它们也并不等长。如果CISC指令集都天生就内嵌了一个完整的有效的RISC指令子集,他们早就那么做了

即使是现在的x86处理器设计者,也绝对不会喜欢最开始的x86的。。。
作者: koppie    时间: 2013-3-13 11:13
largewc 发表于 2013-3-13 11:00
不过还是谢谢你,我找时间看看这本书吧,最近还是很忙,我是无聊的代码测试分子,喜欢自己测试来看结果, ...

David Patterson和John Henessy的两本书是这两个领域内的圣经级别的,看看对理解performance帮助很大。




欢迎光临 POPPUR爱换 (https://we.poppur.com/) Powered by Discuz! X3.4