历史上的今天
返回首页

历史上的今天

今天是:2026年02月02日(星期一)

正在发生

2023年02月02日 | CPU的分支预测对你的代码有什么影响

2023-02-02 来源:zhihu

分支预测的英文名字是「Branch Prediction」


大家可以在Google上搜索这个关键字,可以看到关于分支预测的很多内容,不过要搞清楚分支预测如何工作的,才是问题的关键。


分支预测对程序的影响


我们来看看下面的两段代码


代码1


#include

#include

#include

int main()

{

    // Generate data

    const unsigned arraySize = 32768;

    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)

        data[c] = std::rand() % 256;

    // !!! With this, the next loop runs faster.

    //std::sort(data, data + arraySize);

    // Test

    clock_t start = clock();

    long long sum = 0;

    for (unsigned i = 0; i < 100000; ++i) {

        for (unsigned c = 0; c < arraySize; ++c) { // Primary loop

            if (data[c] >= 128) sum += data[c];

        }

    }

    double elapsedTime = static_cast(clock()-start) / CLOCKS_PER_SEC;

    std::cout << elapsedTime << 'n';

    std::cout << "sum = " << sum << 'n';

}


执行结果


@ubuntu:/data/study$ g++ fenzhi.cpp && ./a.out

21.6046

sum = 314931600000


代码2


#include

#include

#include

int main()

{

    // Generate data

    const unsigned arraySize = 32768;

    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)

        data[c] = std::rand() % 256;

    // !!! With this, the next loop runs faster.

    std::sort(data, data + arraySize);

    // Test

    clock_t start = clock();

    long long sum = 0;

    for (unsigned i = 0; i < 100000; ++i) {

        for (unsigned c = 0; c < arraySize; ++c) { // Primary loop

            if (data[c] >= 128) sum += data[c];

        }

    }

    double elapsedTime = static_cast(clock()-start) / CLOCKS_PER_SEC;

    std::cout << elapsedTime << 'n';

    std::cout << "sum = " << sum << 'n';

}


执行结果:


@ubuntu:/data/study$ g++ fenzhi.cpp && ./a.out

8.52157

sum = 314931600000


第一段代码生成随机数组后,没有进行排序,第二段代码对随机的数组进行排序,执行的时间上发生了非常大的差异。


所以,他们发生了什么事情呢?


导致他们结果不同的原因,就是分支预测,分支预测是CPU处理器对程序的一种预测,和CPU架构有关系,现在的很多处理器都有分支预测的功能。


CPU在执行这段代码的时候


if (data[c] >= 128) sum += data[c];

CPU会有一个提前预测机制,比如前面的执行结果都是true,那么下一次在判断if的时候,就会默认认为是true来处理,让下面的几条指令提前进入预装。


当然,这个判断不会影响实际的结果输出,这个判断只是为了让CPU并行执行代码。


CPU执行一条指令分为几个阶段



既然是分阶段执行,也就是我们正常说的pipeline(流水线执行)。


流水线的工人只要完成自己负责的内容就好了,没有必要去关心其他的人处理。


那如果我有一段代码,如下:



int a = 0;

a += 1;

a += 2;

a += 3;







从这个图上我们可以看到,我们认为是在执行 a = 0结束后,才会执行a+=1。


但是实际CPU是在执行a=0的第一条执行后,马上就去执行a+=1的第一条指令了。


也就因为这样,执行速度上得到了大幅度的提升。

但是对于if() 语言,在没有分支预测的时候,我们需要等待if()执行出现结果后才能继续执行下一个代码。






如果存在分支预测的情况





通过比较我们可以发现,如果存在分支预测的时候,就让执行速度变快了。





那如果预测失败,会不会就影响了执行的时间,答案是肯定的。


在前面的例子中,没有对数组排序的情况下,分支预测大部分都会是失败的,这个时候就会在执行结束后重新取指令执行,会严重影响执行效率。


而在排序后的例子中,分支预测一直处于成功的状态,CPU的执行速率得到大幅度的提升。


如果解决分支预测引起的性能下降


分支预测一定会存在一定的能性下降,想让性能提升的方法就是不要使用这个该死的if语句。

比如,上面的代码,我们可以修改成这样


比如,我们看到的绝对值代码,里面也用了这样的思想


/**

 * abs - return absolute value of an argument

 * @x: the value. If it is unsigned type, it is converted to signed type first.

 * char is treated as if it was signed (regardless of whether it really is)

 * but the macro's return type is preserved as char.

 *

 * Return: an absolute value of x.

 */

#define abs(x) __abs_choose_expr(x, long long,

    __abs_choose_expr(x, long,

    __abs_choose_expr(x, int,

    __abs_choose_expr(x, short,

    __abs_choose_expr(x, char,

    __builtin_choose_expr(

      __builtin_types_compatible_p(typeof(x), char),

      (char)({ signed char __x = (x); __x<0?-__x:__x; }),

      ((void)0)))))))


#define __abs_choose_expr(x, type, other) __builtin_choose_expr(

  __builtin_types_compatible_p(typeof(x), signed type) ||

  __builtin_types_compatible_p(typeof(x), unsigned type),

  ({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)


当然,你也可以这样写


int abs(int i){

   if(i<0)

    return ~(--i);

  return i;

}


所以说,计算机的尽头是数学


推荐阅读

史海拾趣

帝特(DTECH)公司的发展小趣事

2007年,帝特成功获得迪士尼形象授权(泰国),这一里程碑事件标志着帝特品牌在国际市场上的认可度和影响力得到了显著提升。随后,帝特又获得了国内悠嘻猴授权,进一步丰富了其产品线。2008年,帝特荣获“守合同、重信用企业”荣誉称号,这一荣誉不仅是对帝特过去努力的肯定,也为公司的未来发展奠定了坚实基础。

台湾致强(FORT)公司的发展小趣事

致强科技自2005年成立以来,便专注于高功率、低阻值且低TCR(温度系数)的电阻产品研发与生产。团队由一群具有机电整合、金属材料加工及冶金制程丰富经验的专家组成,他们独立研发出全合金材料的电阻生产制程,这一创新不仅区别于业界常见的厚膜或厚膜贴合金制程,还大幅提升了电阻的性能与稳定性。通过不断的技术迭代,致强科技成功推出了一系列高精度、高功率的合金电阻产品,广泛应用于各类电子产品中,满足了市场对高质量电流检知电阻的迫切需求。

Ememory Technology Inc公司的发展小趣事

在2022年,eMemory宣布加入英特尔晶圆代工服务加速器(Intel Foundry Services Accelerator)计划。这一合作标志着eMemory的技术得到了国际半导体巨头的认可。通过这一计划,eMemory为使用英特尔晶圆代工服务的客户提供全球领先的安全IP解决方案,进一步提升了其产品在全球市场的竞争力。

全志(Allwinner)公司的发展小趣事

随着平板市场的逐渐饱和,全志科技开始寻求新的增长点。公司在保持原有产品线优势的同时,积极拓展多品类产品线,实施了营销端BU化,并提出了未来大方向的MANS战略。这一转型不仅增强了公司的市场竞争力,也为公司的长期发展打开了新的局面。

Graseby Infrared公司的发展小趣事
确保电路中的互锁机构工作正常,防止两个接触器同时吸合导致短路事故。
地博电子(DIBO)公司的发展小趣事

近年来,地博电子积极响应行业发展趋势,不断推进数字化转型和精益生产。在2022年,公司导入了精益生产系统,通过优化生产流程、降低库存和浪费等措施,进一步提高了生产效率和产品质量。同时,在2023年,地博电子还导入了OA/SAP信息化系统,开启了数字化转型之路。这些举措使得地博电子在电子材料行业中保持了领先地位,并为公司的未来发展奠定了坚实基础。

请注意,以上故事概要仅为地博电子(DIBO)公司发展历程中的部分关键事实,更多详细信息和数据可参考公司官方资料。

问答坊 | AI 解惑

基于PWM控制的智能充电器的设计

设计的智能充电器要求采用单片机AT89C51进行控制、使用开关电源及A/D、D/A及PWM控制器和电池组等,充电器可以实时采集电池的电压、电流,对充电过程进行智能控制。设计的智能充电器还可以通过串口或RS232和上位PC机进行通讯并给用户显示必要的信息, ...…

查看全部问答>

剥下金钢外衣 带你窥探光驱里的激光管

几天不拆东西手痒痒,拆就拆个没拆过的!这次对一个光驱里的激光管下手。 这个激光管俗称激光头,并不是打开光驱外壳直接看到的光头部分,而是真正发出激光的部分。我们打开光驱外壳能直接看到的只是光学透镜的一部分。 这种激光管有三个引脚,其 ...…

查看全部问答>

总结:轻触按键开关机~~

下面这两个电路都支持长按,是比较实用的电路, 好像还可以用NE555或者运放或者晶闸管来做, 大家还有什么其他的电路,拿出来一起分享吧, …

查看全部问答>

Java/.net程序员如何转向嵌入式

搞了很久的Java和.net,现在想学习下嵌入式,不知道从和下手,麻烦高手指点下,谢谢。 会C/C++,能看懂汇编,熟悉Linux系统 不懂电路,硬件学得不好…

查看全部问答>

个人心得:我是本人聋人嵌入式开发 有经验者请告诉我适合主机?RAM?

我是来自北京联大特殊教育学院 08应届生 大学大专 现在学习C和数据结构基础差不多啊准备下个月去嵌入式开发周末班学习 觉得学习完后我很担心找不到工作啊呀白学半年 所以请求有经验者建议 哪里方面不足告诉我 谢谢 顶 全天在线 …

查看全部问答>

EVC 编译TCPMP的时候,没有的选择ARMV4,是什么原因?

EVC 编译TCPMP的时候,没有的选择ARMV4,是什么原因? 是下载的是0.72RC1的TCPMP源码,请问该如何处理?有做过的吗?网上的编译过程没有说到这个问题的。 请过的DX麻烦了…

查看全部问答>

2440+WINCE5.0 扩充128M SDRAM的问题。

    我使用2440+wince5.0的平台,原先使用2片共64M字节的SDRAM,每片256bit,16bit位宽;现在想使用128M SDRAM,所以用了4片和原先一模一样的SDRAM芯片,在硬件连接上4片sdram芯片的BA0都与addr24连接,BA1都与addr25连接,另外其中两片 ...…

查看全部问答>

有道题想请教一下大家,参考一下你们的答案

串的操作 要求: (1)字符串采用数组存储,建立两个字符串String1和String2。输出两个字符串。 (2)将字符串String2的头n个字符添加到String1的尾部。输出结果。 (3)查找串String3在串String1中的位置,若String3在String1中不存在,则插入 ...…

查看全部问答>

电力行业企业高薪招聘嵌入式开发人员!!

    欢迎满足以下条件之一的有识之士与我们联系,公司网址:     www.nerc.com.cn,发送简历邮箱地址:whl668@epri.ac.cn。     1.具有2年以上电力行业嵌入式产品开发经验。         2. ...…

查看全部问答>

想买台WM5.0的手机做开发,什么手机合适?

wm5.0的PPC哪台性价比高些?大家都是在什么机上做开发的?…

查看全部问答>