RISC-V Optimization Guide(笔记)

官网发表的文章地址:RISC-V Optimization Guide
B站有人做过解读视频,这篇文章也是看视频时做的笔记:视频地址

一、标量整数优化

1.1 常量的具体化

使用lui/addiw将立即数加载至寄存器,当立即数低12位的最高位为1时,需要特殊处理,提前补值0x800

具体的推导过程见:https://zhuanlan.zhihu.com/p/374235855

1.2 有效使用x0寄存器

1)将目标寄存器置0

正确做法如下:

mv x10, x0
or
li x10, 0

不要使用下面方法,因为会有一个读寄存器x10额外的开销。

xor x10, x10, x10
and x10, x10, x0
andi x10, x10, 0
sub x10, x10, x10

2)善于将x0作为指令的源操作数

x0可以折叠到任何指令中作为源操作数(有些情况还可以用作目的操作数),所以避免使用额外指令将0先加载到寄存器中。 下表列出了可以通过谨慎使用 x0 来消除临时寄存器的情况。
在这里插入图片描述

1.3 有效利用指令的立即数域

尽量将范围符合立即数域编码的常量编码到立即数域,而不是通过额外的指令加载到寄存器再使用。

比如访问一个数组,a0存放的是数组基地址,8offset。应该用:

ld t0, 8(a0)

而不是:

addi a1, a0, 8
ld t0, (a1)

这部分的扩展资料:https://www.bilibili.com/video/BV1pN411H7Y3

1.4 善于利用常量池

对64bit的立即数常量,使用常量池。如果该常量在程序中用到多次,收益则会更大。

将一个64bit的数加载至寄存器:

li a0, 0x123456789abcde1

其背后的逻辑可能是,要耗费32byte:

lui a0,0x92
addiw a0,a0,-1493
slli a0,a0,0xc
addi a0,a0,965
slli a0,a0,0xd
addi a0,a0,-1347
slli a0,a0,0xc
addi a0,a0,-543

如果我们使用常量池,常量可以在16个字节中加载,8个字节用于常量,8个字节用于加载它所需的指令。

1:auipc a0, %pcrel_hi(large_constant)ld a0, %pcrel_lo(1b)(a0)
....section .rodata
.p2align 3
large_constant:.dword 0x123456789abcde1

1.5 使用典型的mov指令

使用汇编器 MV 助记符(可转换为 ADDI rd, rs1, 0)将值从一个寄存器复制到另一个寄存器。 例如使用:

mv x10, x11

优先于以下任何指令:

or x10, x11, x0
ori x10, x11, 0
xor x10, x11, x0
xori x10, x11, 0

1.6 使用条件mov代替分支指令

处理器进行分支预测的代价是很高的,一旦分支预测错误,就需要清空流水线,重新开始读取。通过把分支指令替换成条件move是编译器的常见优化,实际上是将控制流的依赖转换成数据流的依赖。而这种转换通常会用到zicond 扩展,也就是czero.eqzczero.nez指令。

czero.eqz rd, rs1, rs2	// if rs2==0 then rd=rs1 else rd=0
czero.nez rd, rs1, rs2	// if rs2!=0 then rd=rs1 else rd=0

原始分支指令版本:

  beqz a0, 1fli a0, constant1j 2f
1:li a0, constant2
2:

初步优化后的指令版本:

li t2, constant1
li t3, (constant2 - constant1)
czero.nez t3, t3, a0
add a0, t3, t2

如果能确定constant112bit范围,还持续优化:

li t3, (constant2 - constant1)
czero.nez t3, t3, a0
addi a0, t3, constant1

如果没有zicond 扩展指令,还可以使用seqz和逻辑组合来达成条件move

li t2, constant1
li t3, constant2
seqz t0, a0			// if a0==0 then t0=1 else t0=0
addi t0, t0, -1		// if t0==1 then t0置为全0 else t0置为全1
xor t1, t2, t3
and t1, t1, t0
xor a0, t1, t3		// if t1是全0 then result=t3 else result=t2

1.7 代码段的Padding

分支跳转的目标或者函数地址的起始能够Padding在一个Cache行的开头地址上,对于整个跳转来说都是比较好的操作。所以在编译一个函数时,会在其结束的时候进行Padding从而占满Cache行,或者在函数的开头Padding让其位于Cache行的开头地址。

  • 函数之间对齐padding使用0 (illegal instruction)
  • 函数内部对齐padding使用Nop或C.Nop
  • 因为在函数内部的执行频率高,乱序执行情况下,流水线在遇见非法指令后可能就不执行后续指令了
  • 而控制流如果传递到函数之间,极有可能是程序出错了,非法指令反而会帮助debug

1.8 将字符数组对齐到更大的对齐单位

如果CPU不支持快速非对齐访问,那么在连续访问字符数组(元素大小8bit)时,lw/sw指令从4字节边界访问,ld/sd8字节边界访问,效率会高很多。

1.9 使用移位指令取出前导位和末尾位(leading/trailing bits)

如将x5的低12位取出:

slli  x6, x5, 20
srli x7, x6, 20

而不是:

lui x6, 1
addi x7, x6, -1
and x8, x7, x5

二、标量浮点优化

2.1 与整数优化相似的部分

  1. 尽量使用尽可能短的代码序列实现同样的功能。
  2. 加载立即数0的折叠。
  3. 内存访问对齐。

2.2 高效控制舍入模式

为什么要舍入? 因为单精度浮点数只取23位尾数(除去隐藏位),而一些运算不可避免的得到的尾数会超过23位,因此需要考虑舍入。

RISC-V的浮点计算舍入模式有两种:静态模式和动态模式。

  • 静态舍入模式:浮点指令的编码中有3位作为舍入模式域,RISC-V架构支持如下五种合法的舍入模式。除此之外,如果舍入模式编码为101或者110 ,则为非法模式;如果舍入模式编码111 ,则意味着使用动态舍入模式。
    在这里插入图片描述
    并不是所有的指令都有舍入模式,根据指令编码格式,以下的指令存在舍入模式的
    浮点运算指令:fadd fsub fmul fdiv fsqrt
    浮点乘加指令:fmadd fmsub fnmadd fnmsub
    浮点转换指令:fcvt.w.s fcvt.s.w fcvt.uw.s fcvt.s.uw
    
  • 动态舍入模式:如果使用动态舍入模式,则使用fcsr寄存器中的舍入模式域。fcsr 寄存器包含舍入模式域。不同的舍入模式编码同样如上图所示,仅支持五种合法的舍入模式。如果 fcsr 寄存器中的舍入模式域指定为非法的舍入模式,则后续浮点指令会产生非法指令异常。

浮点优化,尽可能使用静态模式:

fadd.s f10, f10, f11, rtz

而不是通过csr读写指令来设置FPCSR.FRM:

csrrwi t0, frm, 1      ; 1 = rtz
fadd.s f10, f10, f11
fsrm t0

三、向量优化

3.1 保留v0寄存器作为mask register来使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748242.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库 | MYSQL这个复杂系统如何上手?

当你不知道从何入手研究或解决一个复杂系统的问题时,通常意味着你没有找到合适的切入点或者缺乏对系统整体和细节之间联系的理解。在这种情况下,一个有用的策略是寻找系统的基本原理或构成要素。 小时候,你可能也玩过玩具四驱车。有的四驱车…

Elasticsearch(10) match的使用

elasticsearch version&#xff1a; 7.10.1 Elastic Match是Elasticsearch中用于全文搜索的一种查询语法。它可以将搜索词进行分词&#xff0c;并与目标查询字段进行匹配。 match的语法 GET /<index>/_search {"query": {"match": {"<fiel…

从零开始利用MATLAB进行FPGA设计(三)将Simulink模型转化为定点数据类型

文章灵感来源于MATLAB官方免费教程&#xff1a;HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢&#xff0c;再加上视频讲解老印浓浓的咖喱味&#xff0c;我决定记录利用MATLAB&Simulink&SystemGenerator进行FPGA数字信号处理的学习过程。 往期回顾&am…

Alias许可数量计算

在数字化时代&#xff0c;软件许可数量的合理配置是企业实现成本控制与合规运营的关键。然而&#xff0c;企业在计算软件许可数量时&#xff0c;往往面临诸多困惑。如何精确评估软件需求&#xff0c;确保合规使用&#xff0c;降低成本&#xff0c;成为了企业关注的焦点。Alias许…

grep和vim查找日志文件信息

grep和vim查找日志文件信息 前言&#xff1a;最近排查问题时&#xff0c;经常用到grep和vim查找日志&#xff0c;记录下。 #1、在当前目录下查询文件中是否包含&#xff1a;test内容 $grep -nr test #2、vim查看日志 #2.1、vim文件后&#xff0c;用大写GG&#xff0c;快速…

什么是响应式设计?响应式设计的基本原理是什么?如何做?

文章目录 一、是什么二、实现方式媒体查询百分比vw/vhrem小结 三、总结参考文献 一、是什么 响应式网站设计&#xff08;Responsive Web design&#xff09;是一种网络页面设计布局&#xff0c;页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)…

前端图片预加载和懒加载

前言 在说到对图片资源进行优化时&#xff0c;那就不得不提到图片预加载和图片懒加载&#xff0c;可能很多朋友都了解这两者&#xff0c;但是一直没有很清晰的概念&#xff0c;以及什么时候用&#xff0c;用在什么场景下&#xff0c;今天就来详细的了解一下吧&#xff01; 图…

软考高级:BPR 和 BPM概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【四 (1)数据可视化之如何选用正确的图表】

目录 文章导航一、数据分析中可视化的作用1、揭示数据关联和模式2、支持数据分析和决策3、提升沟通和共享效果4、强调关键信息和发现5、增强故事叙述和记忆效果6、有效增强数据交互性数据7、复杂信息易理解8、数据多维度显示 二、如何选用合适的图表1、简洁性避免使用过于复杂或…

软考高级:企业应用集成概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

八 超级数据查看器   讲解稿   详情3  分享和外观

八 超级数据查看器 讲解稿 详情3 分享和外观 app下载地址 下载地址4 ​ 讲解稿全文&#xff1a; 第3讲 分享 顶栏颜色 外观设置 现在讲解分享功能。点击&#xff0c;会打开分享对话框&#xff0c;我们这里演示2个&#xff0c;可以按照标题做出分享&#xff0c;在第一组…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Badge)

可以附加在单个组件上用于信息标记的容器组件。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 说明&#xff1a; 子组件类型&#xff1a;系统组件和自定义组件&#xf…

异次元发卡源码系统/荔枝发卡V3.0二次元风格发卡网全开源源码

– 支付系统&#xff0c;已经接入易支付及Z支付免签接口。 – 云更新&#xff0c;如果系统升级新版本&#xff0c;你无需进行繁琐操作&#xff0c;只需要在你的店铺后台就可以无缝完成升级。 – 商品销售&#xff0c;支持商品配图、会员价、游客价、邮件通知、卡密预选&#…

腾讯在线文档下载文档html格式

腾讯在线文档下载文档html格式 步骤 chrome 浏览器打开该文档&#xff08;edge不行&#xff09; 同时按住ctrlp快捷键调出腾讯文档内置的打印页面&#xff0c;打印范围要选择整个工作薄&#xff0c;纸张建议调大一点&#xff0c;边距建议较窄&#xff0c;缩放要选择宽度撑满&…

“风口”上的量化大厂“绣球”抛向中低频人才

量化人才这几年是人才舞台上的“香饽饽”。 遵循着低频不如高频、小厂不如大厂的薪资逻辑&#xff0c;各路人才被各路机构“哄抢”&#xff0c;薪资一路走高。 但2024年的“信号”再强烈不过——量化大厂们到了改变的时候了。 而量化大厂们显然对此已“心知肚明”....... “…

空气源热泵、地源热泵和水源热泵三种热泵的优缺点和选型比较

空气源热泵 空气源热泵是由电动机驱动的,利用空气中的热量作为低温热源,经过空调冷凝器或蒸发器进行热交换,然后通过循环系统,提取或释放热能,利用机组循环系统将能量转移到建筑物内用户需求。 1、适用范围广:适用温度范围在-7至40℃,并且一年四季全天候使用,不受阴、…

软件测试 —— 案例系统缺陷报告

知识&#xff1a; 1、缺陷等级&#xff1a; 1-Urgent(致命错误)&#xff1a;影响全局的死机、通信中断、重要业务不能完成 2-Very High(严重错误)&#xff1a;规定的功能没有实现或不完整或产生错误结果&#xff1b;使系统不稳定、或破坏数据等 3-High(一般错误)&#xff1a;…

Github 2024-03-16 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目2Go项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero Gene…

视频和图像编码标准或格式的发展关系

MPEG-2 继承 MPEG-1&#xff1a; MPEG-2 是 MPEG-1 的继任者&#xff0c;用于更高质量和分辨率的视频传输&#xff0c;如 DVD 和数字电视。 MPEG-4 继承 MPEG-2&#xff1a; MPEG-4 在 MPEG-2 的基础上增加了更多的功能和灵活性&#xff0c;适用于多媒体交互和网络传输。 H.2…

java 如何使用Lambda表达式实现不可变性(Immutability)

java 如何使用Lambda表达式实现不可变性&#xff08;Immutability&#xff09; Lambda表达式本身并不直接提供不可变性的特性。不可变性是指一个对象的状态在创建之后不能被修改。Lambda表达式主要用于定义匿名函数&#xff0c;通常用于简化函数式接口的实例创建。 然而&…