首页 > 编程语言 >分支预测,为什么使用 if/else 语句会降低程序效率

分支预测,为什么使用 if/else 语句会降低程序效率

时间:2024-07-14 20:18:28浏览次数:20  
标签:语句 效率 else 执行 CPU 分支

在现代 CPU 架构中,分支预测是为了提高指令执行的效率。然而,如果 if/else 语句的分支走向难以预测,就可能会降低程序效率。这是因为当 CPU 执行到 if/else 语句时,它需要猜测接下来要执行的是 if 分支还是 else 分支。如果 CPU 的预测错误,就需要清空已经预取和执行的部分指令,重新从正确的分支开始取指和执行,这会导致性能开销。

if 语句与运行效率

说起if语句导致程序运行效率下降,就不得不提到CPU的流水线结构,效率降低主要是由于多级流水线结构造成的。

现代的大部分CPU在执行代码时并不是读取一条指令,然后执行一条,而是使用了一种叫做流水线技术的方式,同时去执行多个操作。

流水线的影响

比如三级流水线就是指,CPU在执行一条指令时,同时会读取后面的指令,并对进行译码。(读取、译码、执行)

这样处理的优势很明显,使用流水线技术可以大大的提高执行效率。但是它并不是所有时刻有效的,在程序中执行跳转代码时,CPU 会丢弃流水线现有的结果,因为不执行后面的代码了,提前读取也没有用。

所以在这个时候if语句相对于顺序执行的指令,会有几个时钟周期的差距。但这不是if语句说特有的,所有带跳转结构的语句都会这样(if、switch、for)

分支预测的影响

多级流水线在遇到跳转时,会有几个时钟的周期的影响,但这并不是它被指控运行效率低的主要原因。而是在因为它分支预测部分,它有可能有10-20个时钟周期的影响,在大量使用 if 的地方这种影响将被放大。多级流水在遇到跳转指令时会清空当前流水线,CPU的设计者在设计引入了一种叫做分支预测的技术来进行处理这个问题。

分支预测简单说就是猜测后面的程序会执行那一段代码,并提前将它读取。

例如:一辆火车,在有很多岔道的路上前进,为了不让每次都在岔道停下等待(清空流水线),于是想出了一个办法。现在猜测火车需要前进的方向,如果猜中了火车就可以不用停下等待,而提高效率。但是如果猜错了,则需要倒车回到岔路口重新选择。这样的错误代价就比较高了,而大家所说的效率降低主要源于此。

if-else 对程序结构的影响

在大部分情况下,是不需要考虑if语句对代码执行效率的影响,甚至感觉不到它的存在。
因为大部分情况下,CPU的性能是足够的(性能优化时除外)。但是if-else对程序结构的影响却是不容忽视的,因为可直观的感受到它的存在(可读性),而且对开发和维护有极大的影响。

if-else 对程序效率的影响

简单示例:

package main

import (
    "fmt"
    "time"
)

func testPredictableIfElse() {
    start := time.Now()
    for i := 0; i < 1000000; i++ {
        if i < 500000 {
            // 执行一些简单操作
        } else {
            // 执行一些简单操作
        }
    }
    elapsed := time.Since(start)
    fmt.Printf("Predictable if/else elapsed time: %v\n", elapsed)
}

func testUnpredictableIfElse() {
    start := time.Now()
    for i := 0; i < 1000000; i++ {
        if i%2 == 0 {
            // 执行一些简单操作
        } else {
            // 执行一些简单操作
        }
    }
    elapsed := time.Since(start)
    fmt.Printf("Unpredictable if/else elapsed time: %v\n", elapsed)
}

func main() {
    testPredictableIfElse()
    testUnpredictableIfElse()
}

运行结果:

分别测试了分支走向可预测(例如 i < 500000)和不可预测(例如 i%2 == 0)的两种情况。通过比较它们的执行时间,可以观察到不可预测的分支走向可能导致执行时间更长,从而体现出对程序效率的影响。

标签:语句,效率,else,执行,CPU,分支
From: https://www.cnblogs.com/beatle-go/p/18301946

相关文章

  • 高质量C/C++编程指南总结(四)—— 表达式和基本语句
    1.运算符优先级如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。 2.复合表达式不要编写太复杂的复合表达式。不要有多用途的复合表达式。不要把程序中的复合表达式与“真正的数学表达式”混淆。 3.if语句不可将布尔变量直接与 ......
  • MySQL优化SQL查询语句的策略与实践
    在数据库管理和优化中,针对MySQL的SQL查询优化是提升性能的关键步骤。以下是一些实践性强且高效的策略,旨在减少查询时间,提高系统响应速度:1.精准索引策略,减少全表扫描索引优化:确保在WHERE和ORDERBY子句中涉及的列上创建索引。这不仅加快了数据检索速度,还降低了服务器负担。替......
  • SQLAlchemy 执行原生 SQL 语句
    在使用SQLAlchemy进行数据库操作时,虽然ORM提供了强大的模型映射功能,但有时候直接使用原生SQL语句可能更加简单直率,甚至性能更优。下面我们来看一下如何在SQLAlchemy中执行原生的SQL语句。执行原生SQL语句的步骤构造SQL语句调用session中的execute方法执行,得......
  • 流程循环控制语句
    目录for循环带列表循环不带列表循环类C风格循环while循环语法无限循环使用示例until循环基本语法示例select循环语法格式嵌套循环break和continuebreak的使用continue的使用在shell中循环有以下几种:for循环        while循环until循环selec......
  • C语言-分支与循环(1)
    目录1、if语句1.1if1.2else1.3分支中包含多条语句1.4嵌套if1.5悬空else问题(多个if和一个else对应关系)2、switch语句2.1switch语句中的break2.2switch语句中的default2.3switch语句中的case和default的顺序问题3、关系操作符4、条件操作符4.1什么是条件......
  • SQL中的case when then else end用法
    Case具有两种格式。简单Case函数和Case搜索函数。1--简单Case函数2CASEsex3WHEN'1'THEN'男'4WHEN'2'THEN'女'5ELSE'其他'END6--Case搜索函数7CASEWHENsex='1'THEN'男'8W......
  • Java性能优化-switch-case和if-else速度性能对比,到底谁快?
    场景Java中使用JMH(JavaMicrobenchmarkHarness微基准测试框架)进行性能测试和优化:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131723751参考以上性能测试工具的使用。下面针对Java中对switch-case和if-else在速度方面的性能做测试。注:博客:https://blog......
  • shell语句
    shell语句语句格式:在家目录下编写.vimrc文件,设置tab键缩进为4格vim~/.vimrcautocmdFileTypeshsetaits=4【1】、条件判断双分支#!/bin/bashif[$UID-eq0];thenecho"我是管理员"elseecho"我不是管理员"fi#检测某一目录是否存在#!/b......
  • 实战Qt开发WordBN笔记软件#02 通过Gitee创建YourWordBN仓库;学会GIT常用指令,并实现多分
    01背景【WordBN字远笔记】是天恩软件工作室开发的一款免费笔记软件;WordBN基于VS2019、Qt6.5开发,使用QtQuick(QML)开发语言。本课程将以【WordBN字远笔记】的界面为实战基础,详细介绍如何基于Qt/QML开发语言,从零开始开发一套真正的程序,包括国际化、版本发布、安装包制作等项目......
  • C语言中,scanf和printf函数,分支和循环
    目录1.printf函数1.占位符2.输出格式a.输出宽度b.总是显⽰正负号c.限制小数位数d.输出部分字符串2.scanf函数1.基本用法2.返回值3.占位符4.赋值忽略符3.if语句elseelseif4.关系操作符5.条件操作符(三目操作符)6.逻辑操作符a.逻辑取反操作符!b.逻辑与运算符&......