C/C++的if-else和switch-case想比较,为什么switch-case要快得多?

alphapaopao 2003-01-24 10:41:34
(这里讨论的if-else是指很多段的if-else)

我才想应该是cache的问题。
switch-case的比较判断语句很集中(根据我的反汇编观察),这样cache不会因为
不停的进行比较判断分支而发生刷新。但是if-else的比较判断部分则比较分散,
每一次比较都要跳到很远的地方,这样每次(几乎每次)都需要刷新 cache,
理所当然造成速度很慢。
...全文
898 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
heavensongs 2003-02-16
  • 打赏
  • 举报
回复
关键是switch将数据和代码在内存中进行了分离(把数据pack了)
,提高了cache利用率。if-else 没有。至于分支预测,倒是我自己胡思软想了。
我记得,CPU默认对无条件JMP是预测为向后跳。对有条件转移是上次转移的方向。所以要是一个无条件JMP是往前的,有条件的JMP又是上下震荡的跳,那预测就失败了。让费了不少CPU周期啊。。。。。。。。。。。。
clumsy 2003-02-15
  • 打赏
  • 举报
回复
"分支预测" 是否失效和条件转移指令是向前还是向后转移是没有关系的, 只和这个条件转移指令最后是否发生转移有关.

从我自己看过一些代码来讲, 如果switch比较if真的具有速度优势的话, 一个是采取的如 cui(蚊子王) 所说的转移地址列表的方法; 还有就是switch一般在松散的情况下也多不采取 "比较-转移" 的方法, 而是用 dec(sub)-jz 的指令对, 后者不仅是指令的长度变短了, 速度上也有优势.
heavensongs 2003-02-15
  • 打赏
  • 举报
回复
我猜测大概是因为SWITCH只往一个地方JMP,而IF可以向前,也可以向后JMP,这样,CPU的“分支预测”对IF来说经常会失效(Misprediction),效率低。
可能这是个原因。但我没仔细看过代码。
CHINAhello 2003-02-14
  • 打赏
  • 举报
回复
这个话题不错,看看
紫郢剑侠 2003-02-14
  • 打赏
  • 举报
回复
if 后可跟多个条件, 在编译时出于兼容性, 生成的代码可能比较大
lanying 2003-02-12
  • 打赏
  • 举报
回复
应该是跳转表跟流水线的原因
xiangqian 2003-02-11
  • 打赏
  • 举报
回复
risc cpu同时处理2条以上指令,条件是无寄存器争用
照这样来考虑,只依据跳转代码判断快慢显然不够
alphapaopao 2003-02-11
  • 打赏
  • 举报
回复
这个倒是有道理
紫郢剑侠 2003-02-10
  • 打赏
  • 举报
回复
up
wwtmw 2003-02-05
  • 打赏
  • 举报
回复
原来是这样
绝缘 2003-02-04
  • 打赏
  • 举报
回复
兄弟:你是怎样比较速度的?
蚊子王 2003-02-02
  • 打赏
  • 举报
回复
alphapaopao(炮炮(斯宾诺莎)):
VC不是逐个比较的,如果是,那肯定是DEBUG,而不是RELEASE
zhuxuwei 2003-02-02
  • 打赏
  • 举报
回复
我想原因应该非常简单,
因为IF-ELSE语句里面的条件语句可以是不同的条件,只要你有办法不让他们
产生重复就OK了,但是SWITCH只能对一个变量来产生判断,
之后就可以跳出循环了
alphapaopao 2003-01-30
  • 打赏
  • 举报
回复
cui(蚊子王)
说的没错,但是,对于很紧凑的例子,VC的优化器没有采用数组查询的方法,
而是采用逐个比较
fatmanzhang 2003-01-30
  • 打赏
  • 举报
回复
作个类比:IF-ELSE与SWITCH-CASE之间的区别就好象普通存储器与CAM之间的区别一样
runjiu 2003-01-30
  • 打赏
  • 举报
回复
switch语句只能根据一个变量的值进行转移,但if语句没有这样的限制。当然,判断一个条件比判断一堆条件速度要快的多。
我分析过生成的汇编的代码,switch生成的是一系列的条件判断和转移指令,但if语句没有这样做
蚊子王 2003-01-30
  • 打赏
  • 举报
回复
在实际中,对于val分布比较紧凑的是上面那样的,对于分布疏松的的则可以象折半查询那样来处理。
蚊子王 2003-01-30
  • 打赏
  • 举报
回复
学过编译原理没有,根据编译原理(我后来又对C程序反汇编验证过),switch-case是这样的,举个例子:

switch(val){
case 1:...;break;
case 2:...;break;
case 4:...;break;
case 6:...;break;
case 7:...;break;
default:...;
}

对应的汇编是
addr_tab:
dd def_addr
dd addr1
dd addr2
dd def_addr
dd addr4
dd def_addr
dd addr6
dd addr7

cmp val,7
ja def_addr
jmp dword ptr [eax*4+addr_tab]

addr1:
....
addr2:
....
addr4:
....
addr6:
....
addr7:
....
def_addr:
....
heavensongs 2003-01-29
  • 打赏
  • 举报
回复
我以为这是一个很深奥的问题。
SWITCH——CASE的 CMP/JMP语句都集中在一起,我猜测可能容易优化,
我看过了,没有优化的话,差就差那几个JMP,
alphapaopao 2003-01-27
  • 打赏
  • 举报
回复
heavensongs(农民)
指令可能耗费的CPU时间,可以查询intel的手册
加载更多回复(8)

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧