代码中该使用条件数据传送还是条件控制转移?

序言

最近在看《深入理解计算机系统》一书,明白的程序在计算机中运行的过程,当然也会有一些问题需要记录下来。之前编写代码时没有考虑过的性能问题在 csapp 中也有所了解。条件数据传送和条件控制转移代码的选择就是其中之一。

条件控制转移

  • 所谓条件控制转移—是实现条件操作的传统方法,当条件满足时,程序沿着一条执行路径执行,而当条件不满足时,就走另一条路径,这种机制简单而通用,但在现代处理器上,它可能会非常低效。
  • 条件控制转移代码示例:
long absdiff(long x,long y)
{
	long result;
	if(x < y)
		result = y - x;
	else
		result = x - y;
	return result;
}

就是简单的 if - else 代码,之前从未考虑过代码的效率问题,可能大家之前也经常写出这样的代码吧!

条件数据传送

  • 条件数据传送—这种方法计算一个条件操作的两种结果,然后再根据条件是否满足从中选取一个。
  • 只有在一些受限的情况下,这种策略才可行(并不是所有的条件控制转移都可以写成条件数据传送代码),但是如果可行,就可以用一条简单的体哦阿健传送指令来实现它,条件传送指令更符合现代处理器的性能特性。
  • 简单的例子(与条件控制实现相同的功能)
long cmovdiff(long x,long y)
{
	long rval = y - x;
	long eval = x - y;
	long ntest = x >= y;
	/*Line below requires 
	  single instruction*/
	if(ntest) rval = eval;
	return rval;
}

条件控制产生的汇编代码和条件数据传送的C代码代表的是同一个意思:

long absdiff(long x,long y)
x in %rdi.y in %rsi

absdiff:
	movq %rsi,%rax
	subq %rdi,%rax          //rval = y-x
	movq %rdi,%rdx  
	subq %rsi,%rdx          //eval = x-y
	cmpq %rsi,%rdi          //Compare x:y
	cmovge %rdx,%rax        //if >= rval = eval
	ret                     //return tval

为什么使用条件数据传送的代码比条件控制转移的代码性能要好呢?

  • 在计算机系统中,处理器通过流水线来获得高性能,在流水线中,一条指令的处理要经过一系列阶段,每个阶段执行所需操作的一小部分(例如,从内存取指令、确定指令类型、从内存读数据、执行算术运算、向内存写数据,以及更新程序计数器)。
  • 这种方法通过重叠连续指令的步骤来获取高性能,例如,在取一条指令的同时,执行它前面一条指令的算术运算。要做到这一点,要求能够事先确定要执行的指令序列,这样才能保持流水线中充满了待执行的指令。
  • 当机器遇到条件跳转(分支)时,只有当分支条件求值完成之后,才能决定分支往哪边走。处理器采用非常精密的分支预测逻辑来猜测每条跳转指令是否会执行。只要它的猜测还比较可靠,指令流水线中就会充满着指令。另一方面,错误预测一个跳转,要求处理器丢掉它为该跳转指令后所有指令已做的工作,然后再开始用从正确位置处起始的指令去填充流水线。正如我们看到的,这样一个错误预测会招致很严重的惩罚,浪费大约15~30个时钟周期,导致程序性能下降。

使用条件传送总能提高代码的效率吗?

  • 使用条件传送总能提高代码的效率吗?答案是否定的。例如,如果 then-expr 或者 else-expr 的求值需要大量的计算,那么当相对应的条件不满足时,这些工作就白费了。编译器必须考虑浪费的计算和由于分支预测错误所造成的性能处罚之间的相对性能。但是,说实话,编译器并不具有足够的信息来做出可靠的决定;例如,它们不知道分支可以多好的遵循可预测的模式。
  • 只有当两个表达式很容易计算时,例如表达式分别都只是一条加法指令,它才会使用条件传送。据实验表明,即使许多分支预测错误的开销会超过复杂的计算,GCC还是会使用条件控制转移。

总的来说,条件数据传送提供了一种用条件控制转移来实现条件操作的替代策略。它们只能用于非常受限制的情况,但是这些情况还是相当常见的,而且与现代处理器的运行方式更契合。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值