优化分支代码——避免跳转指令堵塞流水线

计算机组成原理——中央处理器-指令流水(课程笔记) 假设一条指令执行过程为如下5个阶段取指IF从IR或Cache中取指令译码/读寄存器ID操作控制器对指令进行译码,同时从寄存器堆中取操作数执行/计算地址EXE执行运算操作或计算地址访存MEM对存储器进行读/写操作写回WB将指令执行结果写回寄存器堆流水线的设计原则指令流水段个数以最复杂指令所用的功能段个数为准流水段的长度以最复杂的操作所花的时间为准注流水线方式并不能缩短单条指令的执行时间,但对于整个程序来说,执行效率得到了大幅提高指令长度应尽量一致。... 阅读详情

File:      noifop.txt
Name:      优化分支代码——避免跳转指令堵塞流水线
Author:    zyl910
Blog:      http://blog.youkuaiyun.com/zyl910/
Version:   V2.00
Updata:    2006-10-11

(注意修改下载后的扩展名)


一、起因——饱和处理

  在编写图象处理程序时,经常出现RGB值超过[0, 255]范围的情况。这时,得做饱和处理,将越界数值饱和到边界,即这样的代码:
if (r <   0) r =   0;
if (r > 255) r = 255;
if (g <   0) g =   0;
if (g > 255) g = 255;
if (b <   0) b =   0;
if (b > 255) b = 255;


  但这样的代码执行效率是很低的。这是因为if区块会编译成跳转指令,而跳转指令对于严重影响现代超流水线CPU的流水线效率。
  这时CPU产商提出了两个解决方案:一是增加了分支预测硬件,尽量减少跳转指令对流水线的影响;二是设计了MMX/SSE等SIMD指令集,它们天生就有饱和运算指令,而且还可以并行计算。
   分支预测对于循环语句所编译的跳转效果较好,因为在循环时一定会执行跳转,只有最后一次循环结束时才会预测失败。而对于做饱和处理效果就不怎么好了,这 是因为每次循环计算出的RGB值都是不相同的(因为本来就不是同一个像素),预测失败的可能性很大。所以分支预测对饱和处理做的贡献微乎其微。
   而使用SIMD指令呢。那是一种非常完美的解决方案,在有条件的情况下极力推荐SIMD指令。但由于高级语言无法描述SIMD指令,所以只能手工用汇编 编写SIMD代码,这无疑给理解代码带来困难。再者,我们有时需要在像Java、.Net这样的虚拟机平台下编写图象处理程序,而此时是无法直接使用 SIMD指令集的。
  所以,我们需要一种在常规指令集下(能用高级语言表述)做饱和处理的算法,且能避开if跳转。


  先尝试小于零时的饱和处理算法。

  还记得“与”运算有什么作用吗?当一个整数与掩码经行与运算时,全1掩码会保留原值,全0掩码会返回零。
  然后想想如何生成所需的掩码。C语言比较运算的的结果是0和1,怎样将它们变成全0或全1的掩码呢?答案很简单,求负 或 减一。由于求负写法简洁,所以喜欢用求负:
n &= -(n >= 0)

  首先将n与0进行比较。当 n>=0 时,比较结果为1;当 n<0 时,比较结果为0。
  然后求负。当 n>=0 时,结果为-1(全1);当 n<0 时,结果为全0。
  再将原数与上面求得的掩码进行“与”运算。

  有了上面那个算法启发思维后,我们很容易想出处理>255情况的算法:
n = (n | -(n >= 256) ) & 0xFF

  首先将n与256进行比较。当 n<256 时,比较结果为0;当 n>=256 时,比较结果为1。
  然后求负。当 n>=256 时,结果为-1(全1);当 n<256 时,结果为0。
  再将原数与上面求得的掩码进行“或”运算。
  最后跟0xFF进行与运算,使全1变成0xFF(十进制的255)。至于 n<256 的,本来就在[0, 255]范围内,结果不变。

  还可不可以再优化呢?由于一个数不可能同时小于0和大于255,所以可以将着两行代码合并成一行。由于我们一般是将结果保存到一个BYTE型变量中,进行一次强制类型转换就行了,不需要“& 0xFF”。最后,每次写那么长代码太麻烦了,应该将它封装成宏:
#define LIMITSU_FAST(n, bits) ( (n) & -((n) >= 0) | -((n) >= (1<<(bits))) )
#define LIMITSU_SAFE(n, bits) ( (LIMITSU_FAST(n, bits)) & ((1<<(bits)) - 1) )

  bits代表限制多少位,如BYTE就是8。如果觉得参数过多,可以再定义宏,或定义内联函数:
#define LIMITSU_BYTE(n) ((BYTE)(LIMITSU_FAST(n, 8)))

  现在分析一下运算复杂度:
    if办法需要2次比较和2次跳转;
    本办法需要2次比较(、2次将比较结果转为数值)、2次求负、1次与运算、1次或运算。

  可以看出,本办法在减少2次跳转的情况下,增加了共6次的位运算。幸好位运算都是简单指令,都是1个时钟周期内就能完成的指令。所以在现代超流水线CPU情况下,这6次位运算比if跳转开销少。


  上面讨论的只是像C语言那样“比较运算结果是0或1”情况下的算法,如果是像BASIC那样“比较运算结果是0或-1”怎么办呢?其实很简单,我们需要的正是0和-1,BASIC也支持AND、OR、XOR等位运算符。代码就这样写:
by =  ((n And (n >= 0) Or (n >= 256)) And &HFF)


  测试:略。请看old目录下的V100.rar

 

二、推广

  该方法不仅合适做饱和处理,还可以推广到其他方面去。

2.1 条件掩码

#define IFMASKNUM(n, c) ( (n) & -(c) )

参数:
  n: 掩码
  c: 条件。为0或1

返回值: 若c为1,则返回值是n;若c为0,则返回值为0。

 

2.2 MIN与MAX

#define FASTMIN(a, b) ( (a) + ( ((b)-(a)) & -((b)<(a)) ) )
#define FASTMAX(a, b) ( (a) + ( ((b)-(a)) & -((b)>(a)) ) )


解释:
  将b与a进行比较时实际上会执行减法操作,而且前面有“b-a”,这会被编译器优化的。
  注意该方法会产生溢出,所以只有像C语言这样不会抛出整数溢出异常的语言才行。

 

2.3 大小写转换

#define CHARUCASE(c) ( (c) ^ (0x20 & -((c)>='a' && (c)<='z') ) )
#define CHARLCASE(c) ( (c) ^ (0x20 & -((c)>='A' && (c)<='Z') ) )


解释:
'A'的ASCII码是0x41
'a'的ASCII码是0x61
它们相差了0x20,就是D5不同。
所以我在条件满足的时候将该位取反就行了(注意“^”是异或运算符)。

 

2.5 转为十六进制字符

#define TOHEXCHAR(i) ('0' + (i) + ( ('A' - ('0'+10)) & -((i)>=10) ))


解释:
其中的“( ('A' - ('0'+10))”会编译优化成常数的。
至于如何进行逆转换,估计只有用查表法了。 
计算机组成原理第五章---中央处理器第三部分:指令流水线,多处理器和硬件多线程 本文重点介绍了指令流水线的相关知识,同时对多处理器系统和硬件多线程也根据考纲进行了简单介绍。 阅读详情

相关推荐

深入解析MPC7450:经典PowerPC RISC核心的指令流水线、缓存与异常处理实战

在计算机体系结构中,RISC(精简指令集计算机)设计哲学通过固定长度指令、加载/存储架构和硬件管理流水线,旨在提升指令级并行与执行效率。其核心原理在于简化指令解码与硬件控制逻辑,将复杂性交由编译器优化,从而在相同工艺下实现更高的主频和能效比。这一技术价值在嵌入式系统、网络设备和实时控制等对性能与功耗有严苛要求的领域尤为突出。本文以Freescale(现NXP)的经典PowerPC处理器MPC7450为具体案例,深入剖析其超标量流水线如何实现指令级并行,以及多级缓存架构的管理策略。文章将结合**缓存一致性**

weixin_30140399的博客 286

【五级流水线CPU】—— 5. 转移指令(14条)

转移指令(14) 一共14条指令,分为两类: 跳转指令(绝对转移):jr、jalr、j、jal 分支指令(相对转移):b、bal、beq、bgez、bgezal、bgtz、blez、bltzal、bne 1. 延迟槽 不MEM进行判断,直接在译码阶段进行判断 在流水线译码阶段进行转移判断,并且转移发生,那么会有1条无效指令,导致浪费了一个时钟周期。为了减少损失,规定转移指令后面的指令位置为“延迟槽”,延迟槽中的指令被称为“延迟指令”。延迟指令总是被执行,与转移发生与否没有关系。 2. 转移分支指令 2

Running Snail 3023

ARM Cortex-A72微架构优化与指令级性能调优

现代处理器架构设计中,超标量乱序执行是提升指令级并行度的核心技术。ARMv8-A架构的Cortex-A72通过12级流水线设计和8个功能单元,实现了每周期3条指令的发射能力。在嵌入式系统和移动计算领域,理解处理器微架构特性对性能优化至关重要。通过分析指令延迟与吞吐量特征,开发者可以合理调度整数/浮点运算、优化内存访问模式,并利用SIMD指令实现算法加速。特别是在图像处理、密码学计算等场景中,结合ASIMD指令集和硬件加速单元,可使关键算法获得3-15倍的性能提升。本文以Cortex-A72为例,详解如何通过

weixin_32242475的博客 332

流水线的指令解读及相关计算

前言        指令通常存储在主存中,默认情况下由程序计数器进行依次读取,除非遇到 JMP 命令才会进行跳转继续执行。而执行一条指令的过程一般如下: ①先从存储器中读取一条指令然后送到 1、流水与非流水的简单介绍 2、 ...

aiden_kevin的博客 5005

网络处理器CST应用开发:C代码优化与多核并行实战指南

在嵌入式系统与高性能网络处理领域,理解硬件架构是软件优化的基石。网络处理器(NP)作为一种专用集成电路,其核心价值在于通过多核并行与硬件加速,实现远超通用CPU的数据包处理吞吐量和低延迟。其原理在于将复杂的网络功能(如包分类、流量管理)卸载到专用的处理单元和可编程核心上,通过精细的指令调度和内存访问控制来榨取硬件性能。这要求开发者从通用编程思维转向体系结构感知的编程,技术价值体现在对有限片上资源(如指令内存IMEM、数据内存DMEM)的极致利用。应用场景广泛覆盖路由器、交换机、防火墙等网络设备的线速处理。本

diehe5608的博客 398

LLCE、PFE模块,二层交换/桥接的通用学习转发机制

NXP 文档里给出的正式全称如下:面向 CAN/CAN-FD、LIN、FlexRay 的“低延迟通信引擎”,用多核 M0 固件做报文收发、过滤、路由,把主 CPU 中断负荷降到几乎 0。“数据包转发引擎”,负责以太网帧的分类、修改、转发、VLAN/NAT/IPsec 等 offload,支持 2 Gbit/s 线速且主机负载 ≈0。两者都跑各自固件,通过内部 AXI 桥可互连,实现“CAN→ETH”零主核参与的硬件级网关功能。是它们都集成在。

qq_25461777的博客 1305

C代码优化方法小结

1.《C代码优化方案 》 http://www.docin.com/p-144092446.html 2.《代码优化-之-优化除法 》 http://blog.youkuaiyun.com/housisong/article/details/1116423 3.《代码优化-之-优化条件分支 》 http://blog.youkuaiyun.com/housisong/article/details/181211

千里河山 513

0009 用VisualStudio设计Max工具

这次分享个独家专利^)^:在Visual Studio中设计3dsMax脚本工具界面。 某次做原型设计时,需求改来改去,实在懒得搞GUI;虽然也尝试在Axure RP里画原型,但还是Visual Studio更顺手,也更容易测试一些交互,就直接在VS里做了。后来突发奇想,想实验一把能否直接用到Max里去,结果没想到成功了,效果还挺好。发现了新大陆,记录一下。   开始: 在VS里新建W...

whwst的专栏 770

深入探讨用位掩码代替分支(1):利用带符号移位生成掩码

  几年前我写了一篇“优化分支代码——避免跳转指令堵塞流水线”(http://blog.youkuaiyun.com/zyl910/article/details/1330614)。因当时是整理笔记,有些粗略。这几年又有了新的心得,故决定深入探讨,顺便回答网友评论。   housisong(http://blog.youkuaiyun.com/housisong)提到了用利用带符号移位生成掩码——(假设n是32bit有...

weixin_30770495的博客 116

Type-c超声波切割刀

接下来,我将提供Type-C超声波切割刀项目的C代码实现示例,代码将按照上述分层架构和模块化设计进行组织。为了达到3000行以上的代码量,我将尽可能详细地实现各个模块的功能,并添加必要的注释和错误处理。通过采用分层架构和模块化设计,我们可以建立一个可靠、高效、可扩展的系统平台,为产品的成功奠定坚实的基础。实际项目中,需要更详细的硬件驱动、更完善的功能模块、更严格的测试验证和更周全的维护升级计划。针对Type-C超声波切割刀这个项目,我将从以下几个方面详细阐述最适合的代码设计架构,并提供具体的C代码实现。

lianmengde的博客 1194

高通camx架构学习(零)—— 深入理解Camera 硬件抽象层

从上面的定义可以看出,主要是通过hw_module_t 代表了模块,通过其open方法用来打开一个设备,而该设备是用hw_device_t来表示,其中除了用来关闭设备的close方法外,并无其它方法,由此可见谷歌定义的HAL接口,并不能满足绝大部分HAL模块的需要,所以谷歌想出了一个比较好的解决方式,那便是将这两个基本结构嵌入到更大的结构体内部,同时在更大的结构内部定义了各自模块特有的方法,用于实现模块的功能,这样,一来对上保持了HAL的统一规范,二来也扩展了模块的功能。

图像学习之旅 1670

深入解析CPU指令流水线:从5级模型到现代优化实战

指令流水线是CPU微架构的核心技术,它通过将指令执行过程划分为多个阶段并行处理,显著提升了处理器的吞吐率。其基本原理类似于工业装配线,通过重叠执行不同指令的各个阶段来实现指令级并行。这项技术的核心价值在于它构成了现代高性能CPU的基石,直接影响着主频提升、能效比以及指令级并行度的挖掘。在实际应用场景中,从嵌入式系统到服务器处理器,流水线设计都至关重要。然而,流水线也引入了数据冒险、控制冒险和结构冒险等挑战,需要通过前递、分支预测和乱序执行等技术来解决。本文以经典的5级流水线模型为切入点,结合数据冒险和分支预

weixin_30509393的博客 477

RBF(径向基神经网络)基础解析与代码实例:拟合任意函数

目前RBF这一强大工具已经被基本证实可以拟合任意函数! 在机器学习领域,神经网络是一种强大的工具,用于解决各种复杂问题。其中,径向基函数(RBF,Radial Basis Function)神经网络以其独特的结构和优异的性能,在非线性函数逼近、模式识别等领域表现尤为突出。RBF神经网络是一种前馈神经网络,其隐含层节点的激活函数采用径向基函数,具有更强的局部逼近能力和更快的收敛速度。

橙色小博的博客,励志在人工智能领域发光发热! 1605

《计算机组成与设计》阅读笔记——流水线CPU的设计

单周期CPU 单周期构造的缺陷 由于要保证所有指令在一个周期内完成,时钟周期会很长,也限制了时钟频率的提升 各种指令执行的长短时间不一(比如加法和存数据到内存)时间短的指令效率被浪费 指令类型 指令分为R-type,I-type和J-type 一般由最高6位区分 R-type指令主要执行ALU运算,具体运算由最低6位的funct段决定 I-type指令主要是和地址与常数相关的指令,如存...

firefly 2415

HiCMAE 论文复现:基于 RAVDESS 数据集的音视频情感识别

多模态情感识别是人工智能领域的重要研究方向,旨在通过结合多种感知模态(如音频、视频、文本等)来更准确地识别人类情感状态。与传统单模态方法相比,多模态方法能够利用不同模态间的互补信息,提高情感识别的鲁棒性和准确性。 RAVDESS(Ryerson Audio-Visual Database of Emotional Speech and Song)是一个常用的多模态情感识别数据集,包含24位专业演员(12名男性,12名女性)表达的8种情感状态(中性、平静、快乐、悲伤、愤怒、恐惧、厌恶和惊讶)的音视频数据。

max500600的博客 498

YOLOv11改进 | 网络结构代码逐行解析(二) | yolov11中的Mosaic增强详解

本文给大家带来的是YOLOv10中的Mosaic增强代码的详解,可能有部分人对于这一部分比较陌生,有的读者可能知道Mosaic增强但是不知道其工作原理,具体来说Mosaic增强就是指我们的数据集中的图片在输入给模型之前的一个处理过程(我们的图片并不是直接就输入给模型了,大家的训练结果中的结果检测图片大家可以看到数据集中多个图片会组合在一起这就是简单的Mosaic增强),下面我就来讲解一下其在YOLOv10中工作原理和代码定义,下面图片为一个Mosaic增强后的图片。​。

Snu77的博客 5023

ARM流水线技术:原理、优化与应用实践

流水线技术是计算机体系结构中的核心概念,通过将指令执行过程分解为多个阶段实现并行处理,显著提升处理器性能。ARM作为RISC架构代表,其流水线设计体现了精简指令集的优势,从经典的3级流水线演进到现代Cortex系列的15级超标量设计。理解流水线工作原理对于处理数据冒险、控制冒险等挑战至关重要,特别是在嵌入式系统和实时应用中。通过编译器优化、指令调度和内存访问模式调整,开发者可以最大化ARM流水线的效率。当前ARM流水线技术正朝着智能分支预测、异构计算和安全增强方向发展,为AI和物联网应用提供更强支持。

weixin_34409357的博客 361

华为OD机试双机位C卷-用户入网定期复评(C/C++/Py/Java/Js/Go)

华为OD机试(机考)双机位C卷 【用户入网定期复评】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【用户入网定期复评】。

qq_45776114的博客 841

正确的优化分段函数形式的多重分支代码

File:      fastmif.txtName:      正确的优化分段函数形式的多重分支代码Author:    zyl910Blog:      http://blog.youkuaiyun.com/zyl910/Version:   V1.00Updata:    2006-10-13一、基本代码  有时候,我们会碰上这样的多重分支代码:char szbuf[10];if     (scor

zyl910的专栏 2805

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

e500处理器流水线优化:从硬件原理到软件性能提升实践

在现代处理器架构中,流水线技术是提升指令吞吐率的核心机制,它通过将指令执行过程分解为多个阶段并行处理来提升性能。其基本原理涉及取指、解码、发射、执行和写回等阶段的协同工作,技术价值在于通过指令级并行最大化硬件利用率。在嵌入式系统、高性能计算等对实时性要求严苛的应用场景中,深入理解流水线行为对软件优化至关重要。本文聚焦于PowerPC e500核心的流水线细节,剖析其解码阶段的串行化控制、发射阶段的资源仲裁以及执行阶段的重播机制等关键硬件行为。通过分析指令属性与流水线互锁的关系,探讨如何优化内存访问模式、平衡

weixin_30522183的博客 356

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

图解计算机组成原理:流水线处理器的三大冒险问题及解决方案

本文深入解析了流水线处理器面临的三大冒险问题——结构冒险、数据冒险和控制冒险,并提供了相应的解决方案。通过图解和实例分析,详细介绍了分离缓存、数据转发技术和分支预测等优化方法,帮助读者深入理解计算机组成原理中的流水线技术及其性能优化策略。

weixin_30352645的博客 426

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

独占线程太多怎么办_【X86处理器功能详解】 英特尔 超线程技术

今天分享一下超线程技术,以及在现实工作负载中为了达到最大性能,如何选择是否开启HT。超线程是什么?超线程(Hyper Threading),是允许一个CPU执行多个控制流的技术,就是将一颗具有超线程功能的物理CPU核心变成两颗逻辑CPU核心,而逻辑CPU核心对操作系统来说,跟物理CPU核心并没有什么区别。因此,操作系统会把工作线程分派给这两颗(逻辑)CPU核心上去执行,让(多个或单个)应...

weixin_34135180的博客 1029

计算机体系结构高效复习:从性能公式到流水线、缓存与虚拟内存实战

计算机体系结构是理解计算机底层工作原理的核心学科,其设计始终围绕提升性能这一中心目标。性能公式(CPU执行时间 = 指令数 × CPI × 时钟周期)是分析一切设计权衡的基石。从原理上看,现代处理器通过流水线、多级缓存和虚拟内存等关键技术来优化性能。流水线通过指令级并行提升吞吐率,但需解决数据冒险、控制冒险等挑战;缓存则基于局部性原理,在CPU与主存间建立高速缓冲区,有效降低平均访存延迟。这些技术的工程价值在于,它们共同构成了从指令集架构到微架构的实现路径,是构建高效、可靠计算系统的关键。在应用场景上,无论

weixin_33709590的博客 356
上一篇: 开篇
下一篇: Linux configure 参数解释
DigBug
博客等级 码龄20年 15粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值