自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

七妹的博客

铁汁,家里来客了~

  • 博客(159)
  • 收藏
  • 关注

原创 Golang编译优化——死代码删除

b *Blocki int死代码删除的在deadcode函数中实现,对于一个函数f,删除其死代码的过程如下:首先检查函数f是否经过寄存器分配(regalloc)。如果已经经过寄存器分配,那么无法进行死代码删除,因为寄存器分配可能生成多余的 SSA 代码,会导致一些必需的移动操作被消除。调用,找到函数f中可达的基本块,将其放入数组reachable。删除从不可达块到可达块的边,确保不会有从死代码到活跃代码的控制流传播。

2024-04-18 19:41:01 434

原创 Golang编译优化——消除Copy指令

以下是Go编译器对某个代码段编译生成的SSA IR摘选,对于Golang SSA IR的介绍我写了文章,但是在犹豫要不要发。编译器在中间代码生成和优化阶段,不可避免的会生成一些非必要的指令,如上面b3块中的。消除Copy指令的操作会遍历所有IR,迭代找到Copy指令的最终引用,将其替换到合适的位置。下列,引用参数v12和v13会分别替换为其指令的参数v22和v9。而v12和v13这两条指令如果在其他地方都没有引用,它将变成死代码,会在后续的死代码删除优化(以后会写文章来讲解)中将其消除。

2024-04-11 16:50:12 696

原创 线程局部存储(TLS)

(Thread Local Storage,TLS),是一种变量的存储方法,这个变量在它所在的线程内是全局可访问的,但是不能被其他线程访问到,这样就保持了数据的线程独立性。而熟知的全局变量,是所有线程都可以访问的,这样就不可避免需要锁来控制,增加了控制成本和代码复杂度。

2024-03-27 10:45:20 902

原创 RISC-V Optimization Guide(笔记)

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

2024-03-12 19:35:44 936

原创 Go语言圣经总结

如果没有足够的增长空间的话,appendInt函数则会先分配一个足够大(2*len(old_slice),这个扩容算法因不同语言不同)的slice用于保存新的结果,先将输入的x复制到新的空间,然后添加y元素。当调用一个函数的时候,函数的每个调用参数将会被赋值给函数内部的参数变量,所以函数参数变量接收的是一个复制的副本,并不是原始调用的变量。因为函数参数传递的机制导致传递大的数组类型将是低效的,并且对数组参数的任何的修改都是发生在复制的数组上,并不能直接修改调用时原始的数组变量。

2024-01-18 14:37:01 1165

原创 DWARF常见section总结

中源代码行号与机器码指令地址之间的映射关系,要先读取其中的内容,再按照规则和方法解析读取到的内容,最终就可以得到如上面代码段所示的内容。节中声明了很多中不同的Dwarf类型组合(我们可以想象为C语言中的结构声明,而这些类型都是DWARF格式约定好的类型),然后在。段包含了程序中的行号信息,通过读取、解析该段的内容,我们就能知道源代码行号与机器码指令地址之间的映射关系。节中的那个类型,也就是说明自己是那个结构的实例。这两个节是天生在一起的两个节,它们是一个“实例和类型”的关系,也就是。节中的一个结构的实例。

2023-12-22 17:12:17 1293

原创 Go Test测试总结

模糊测试的方式,运行 Fuzz 测试,默认情况下不进行模糊测试。指定时,命令行参数必须与主模块中的一个包完全匹配,而正则表达式必须与该包中的一个模糊测试完全匹配 ,模糊测试将在常规测试、基准测试、其他模糊测试的种子语料库和 Example 完成后进行。包用于调用相应的测试函数,接着构建并运行、报告测试结果,最后清理测试中生成的临时文件。:列出所有符合正则表达式的顶层测试,不会运行任何测试。本地目录模式,即直接运行当前目录下的包,即。,测试该目录下的所有包,在该模式下,包列表模式,运行指定包下的测试,

2023-09-20 11:03:11 1525 2

原创 LuaJIT Bytecode结构布局

假设现在有两个寄存器PC和INS,PC存放Bytecode的地址,INS存放PC对应地址处的Bytecode值,则可以利用以下伪代码对Bytecode访问,其中。中的汇编代码在预处理阶段变成二进制机器码,然后再使用内存映射将机器码映射到虚拟内存,等运行时便可以直接运行被映射的二进制代码。中查找相应的函数指针,再执行相应的函数。等解释执行的逻辑完成,开始让PC指向下一条Bytecode指令,重复同样的过程。运行时被映射的二进制代码的地址(函数指针),存放在。类型的动态数组中,数组的初始。

2023-06-15 17:25:58 3909 5

原创 简单介绍一个编译器的结构(下)

经过中间代码生成过程产生的中间代码是正确的,但未必就是更“好”的,所以我们要对中间代码做一些优化,使其可以更“好”。这个“好”是个泛指,比如我们希望它生成的汇编代码量可以更小(GCC加-Os)、或者生成的汇编代码执行时的内存使用量更小、或者生成的汇编代码执行速度可以更快(GCC加-O[1/2/3])。一般而言,最期望的“好”还是执行速度可以更快,我们接下来的介绍也是以这部分内容展开。

2023-06-15 17:22:04 724

原创 编译器设计(十四)——寄存器分配

在程序中的每个位置上,寄存器分配器会确定哪些值将位于寄存器中,哪个寄存器将容纳哪些值。如果分配器无法将某个值在其整个生命周期均保持在寄存器中,那么在其生命周期的部分或全部时间,该值必须存储到内存中。分配器可能会将一个值逐出到内存,因为代码包含的活跃值数据超出了目标机寄存器集合的容量。另外,在一个值各次使用之间的间歇,它可能被保存到内存中,因为分配器无法证明它能够安全地驻留在寄存器里。

2023-05-23 17:25:16 1929

原创 使用Makefile笔记总结

GNU的make很强大,它具有一些隐晦规则,可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个.o文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。只要make看到一个.o文件,它就会自动的把.c和.h文件加在依赖关系中,如make找到一个print.o,那么print.c和print.h,就会是print.o的依赖文件,并且 cc -c print.c 也会被推导出来。

2023-05-23 17:16:55 945 1

原创 多核处理器结构

从20世纪90年代后期开始,随着半导体工艺的发展,单芯片上晶体管数目大幅增多,多核处理器得到了很好的发展。多核处理器(Multicore Processor)在单芯片上集成多个处理器核,也称为单片多处理器(Chip Multi-Processor,简称CMP),通过聚合芯片上的多个处理器核的计算能力来提高应用程序执行性能。各处理器核并行执行线程(或者进程)发出读/写(load/store)访存指令,这些访问指令的执行次序如何约定,使得应用程序员可以利用这些约定来推理程序的执行结果。片上Cache如何组织?

2023-04-01 20:07:17 3093

原创 使用Shell笔记总结

6、使用readonly可以将变量定义为只读变量,只读变量就是一个常量。unset 命令可以删除变量,变量被删除后不能再次使用,不能删除只读变量。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小,数组元素的下标由 0 开始。等,可以保有其符号代表的特性,即可以有变量、转移字符;3、在一串指令的执行中,还需要藉由其他额外的指令所提供的信息时,可以使用反单引号。

2023-04-01 17:33:59 1370

原创 LuaJIT 栈帧布局(stack frames layout)

但是用堆内存代替寄存器和运行时栈在虚拟机层面的访问时效是相同(都是访问内存),所以我们可以效仿没有寄存器文件的龙芯处理器,在LuaJIT虚拟机中去除寄存器这一概念,只保留LuaJIT的运行时栈,LuaJIT也正是这么做的。主调函数调用被调函数之前,会先把被调函数的stack结构布置好,函数对象、参数放入指定位置,并在stack上留下存放PC的空间(这个PC以后再介绍吧,其实就是放函数调用返回后,将要执行的指令的)。,将slot 1中的值和slot 0号中的值相加,结果存放在slot 1号中。

2023-03-20 11:39:45 693

原创 LuaJIT 常量数组(constant array)

Lua source中出现的常量依次是131072、262144、1310721、131072,它们均为const number,所以在解析时将131072放在了索引0处,262144放在了索引1处,1310721放在了索引2处,解析到第二个131072时,发现该常量已经出现过且在索引0处,此时只需要将0放在操作数D上即可(中Node结构体,val和上面说过的TValue数组的索引对应,作为常量表slot,key则是常量值或字符串的sid,next存放下一个元素的地址。HashTable节点类型的定义是。

2023-03-17 13:37:01 628

原创 位运算实战技巧总结

两个负数相加可能会产生负溢出,负溢出结果会变为正数。如果两个数x和y符号相同,符号位异或结果为0;符号不同,符号位异或结果为1。如果一个正数是2的次幂,则这个数的二进制表示中只含有一个1。循环消去,当最后x值为0时,便可以求出二进制中1的个数。会找到第一个大于x的数,且它正好是n的整数倍。则是先对b按位取反,再将结果与a按位与运算。是最高权重,如果x,y的和数据溢出,则和模。运算的二进位结果,相异为1,相同为0。设整数n类型为int_8,值为3,则。成立,n为偶数,否则为奇数。比x,y中的任何一个值都小。

2023-02-15 18:11:24 360

原创 编译器设计(十三)——指令调度

对程序块或过程中的操作进行排序以有效利用处理器资源的任务称为指令调度调度器的输入是由目标机汇编语言操作组成的一个部分有序的列表,输出是同一列表的一个有序版本。一组指令的执行时间严重依赖于其执行顺序,指令调度会重排一个过程中的各个指令,使每个周期执行尽可能多的指令,以改进其运行时间。对于整数加法或减法是1个周期;对于整数乘法或浮点加减法是3个周期;对于浮点乘法是5个周期;对于浮点除法是12-18个周期;对于整数除法是20-40周期。

2022-12-29 11:07:26 1918

原创 LuaJIT SSA IR介绍

LuaJIT资料挺少,可以一手学习的基本上只有官方文档:http://wiki.luajit.org/SSA-IR-2.0,但是目前这个文档的介绍被作者删了。在文档被删之前,我按照自己的理解,对官网上的部分内容做了记录。等后面我想优化了,再把这一块内容好好优化一些,毕竟写这边文章的时候,我刚接触LuaJIT,对LuaJIT掌握的还

2022-12-09 16:47:46 724

原创 LuaJIT Bytecode介绍

关于Bytecode介绍的官方文档:[http://wiki.luajit.org/Bytecode-2.0](http://wiki.luajit.org/Bytecode-2.0)但是最近发现作者将Bytecode和SSA IR的介绍的文档删除了,也不知道是为什么。虽然那些文档写的不太详细,除非看它们在LuaJIT中的具体实现代码,否则很难看懂。这篇文章我尽量说详细点,会结合Bytecode在代码中的具体定义,希望对需要的同学有所帮助。在LuaJIT的源码中,关于Bytecode的指令格式的定义

2022-12-09 16:28:07 1098

原创 编译器设计(十二)——指令选择

指令选择(instruction selection),将编译器的IR映射到目标ISA,这实际上是一个模式匹配问题,其复杂性源自常见的ISA为(即使是简单的)操作提供的大量备选实现方案。在其最简单的形式下,编译器可以为每个IR操作提供一个目标ISA操作序列。由此形成的指令选择器提供了一个类似模板的展开,最终会生成正确的代码。遗憾的是,这种代码对目标机资源的利用比较糟糕。更好的方法会对每个IR操作考虑许多可能的候选代码序列,并从中选择预期代价最低的代码序列。本章阐述指令选择的两种方法:一种基于树模式匹配。

2022-12-09 16:19:44 1573 1

原创 编译器设计(十一)——标量优化

所谓的标量优化,指的是单个控制线程下代码的优化。大多数优化器都被构建为一系列处理趟(pass),如下图所示。每趟以IR形式的代码作为其输入,以重写后的IR代码版本作出其输出。这种结构将实现划分为若干小片段,从而避免了大型单块程序引起的部分复杂性。这允许独立地构建并测试各个处理趟,简化了开发、测试和维护。这建立的方法颇为自然,使编译器能够提供不同的优化级别,每个级别规定了一组需要运行的处理趟。趟结构使编译器编写者能够多次运行某些趟(如果需要的话)。

2022-11-24 11:20:13 814

原创 使用readelf和objdump查看ELF常见段

就是就是将几个输入目标文件加工后合并成一个输出文件,整个链接过程分两步:空间与地址分配、符号解析与重定位。的3大步骤:启动动态链接器本身 → 装载所有需要的共享对象 → 重定位和初始化。中对这些段又做了详细的解释,用到的时候只需查询即可。中给出了其中常见的段,解释了每个段的含义和用途。查看数据段相关的值需要。查看代码段相关的内容只需要。将16进制打印出来;

2022-11-02 13:14:56 5390

原创 编译器设计(十)——数据流分析

数据流分析是用于编译时程序分析的经典技术,它使编译器能够推断程序中的值在运行时的流动。在简单的情况下,静态分析可以生成精确的结果,此时编译器能够确切地知道在代码执行时到底将发生什么。如果编译器能够推导出精确信息,那么它可以将表达式或函数的运行时求值操作替换为对(编译时预计算)结果的立即数加载操作。另一方面,如果代码从任何外部来源读取值、涉及(即使很少的)控制流,或者遇到具有歧义的内存引用(指针、数组引用或引用调用参数),那么静态分析会变得困难得多,而分析的结果也会变得不那么精确。

2022-10-25 14:12:34 1988

原创 计算机组成原理和结构

现代计算机都采用存储程序结构,又称为冯·诺依曼结构,是1945年匈牙利籍数学家冯·诺依曼受宾夕法尼亚大学研制的ENIAC计算机结构的启发提出的,是世界上第一个完整的计算机体系结构。冯·诺依曼结构的主要特点是:冯·诺依曼计算机的工作原理如下图5.1所示。运算器是计算机中负责计算(包括算术计算和逻辑计算等)的部件。运算器包括算术和逻辑运算部件(Arithmetic Logic Units,简称ALU)、移位部件、浮点运算部件(Floating Point Units,简称FPU)、向量运算部件、寄存器等。其中

2022-10-10 21:08:27 3386 1

原创 常见上下文切换场景

函数调用是用户主动发起的指令流和上下文改变。普通的转移指令只改变指令流不改变上下文,函数调用则通过ABI约定实现了一定的上下文变化。函数调用通常伴随着栈帧的变化,此外部分寄存器也会发生变化。根据ABI的约定,像这样约定由被调用者保存(Callee Save)的寄存器在函数调用前后保持不变,而通用暂存器、参数寄存器等则不保证维持调用前的值。不同指令系统实现函数调用的方式有所不同。LoongArch采用比较典型的RISC做法,硬件仅仅提供一个机制(bl或者jirl指令),用于在改变指令流的同时保存一个返回地址到

2022-09-28 18:16:12 372

原创 编译器设计(九)——优化简介

代码优化的目标是在编译时发现有关程序运行时行为的信息,并利用该信息来改进编译器生成的代码。改进可能有许多种形式。优化最常见的目标是提高编译后代码的运行速度。但对于某些应用程序来说,编译后代码的长度要比其执行速度更重要。例如,考虑某个将烧录到只读存储器的应用程序,其代码长度会影响整个系统的成本。优化的其他目标包括降低执行的能耗、提高代码对实时事件的响应、降低对内存的总访问量、优化寄存器的使用等。有两个关于优化的比较经典的例子,后面补上。

2022-09-17 15:09:29 3267

原创 编译器设计(八)——代码形式

如果允许用户获得结构数组中数组元素的地址,那么编译骈在内存中对数据进行布局时,结构数组的布局将呈现为多个布局相同、在内存中连续出现的结构实例。如果编译器将一个静态值保持在寄存器中,那么在过程中第一次使用该值之前,必须将其从内存加载到寄存器,在离开过程之前(退出该过程时,或在过程内部调用其他过程时),必须将其写回到内存。,命名值a,未命名值b + 1),编译器都必须确定在何处存储这些值:是在内存中还是在寄存器中,不管是哪种情况,都要给出具体的位置。、最后一维的下界、B中一个元素的长度,来计算一个偏移量。

2022-09-09 09:19:37 715

原创 链接装载与库:第十二章——系统调用与API

在现代的操作系统里,程序运行的时候,本身是没有权利访问多少系统资源的。由于系统有限的资源有可能被多个不同的应用程序同时访问,因此,如果不加以保护,那么各个应用程序难免产生冲突。所以现代操作系统都将可能产生冲突的系统资源给保护起来,阻止应用程序直接访问。这些系统资源包括文件、网络、IO、各种设备等。举个例子,无论在Windows下还是Linux下,程序员都没有机会擅自去访问硬盘的某扇区上面的数据,而必须通过文件系统;也不能擅自修改任意文件,所有的这些操作都必须经由操作系统所规定的方式来进行,比如我们使用。

2022-09-05 17:02:02 735

原创 链接装载与库:第十一章——运行库

除了之前的14个头文件,剩下的15个头文件(C89标准)为:assert.h、ctype.h、errno.h、float.h、limits.h、locale.h、math.h、setjmp.h、signal.h、stdarg.h、stddef.h、stdio.h、stdlib.h、string.h、time.h。glibc的启动过程在不同的情况下差别很大,比如静态的glibc和动态的glibc的差别,glibc用于可执行文件和用于共享库的差别,这样的差别可以组合出4种情况,这里只选取最简单的。

2022-09-03 16:11:17 980

原创 链接装载与库:第八章——Linux共享库组织

这样保证了所有的以SO-NAME为名的软链接都指向系统中最新版的共享库。当共享库进行升级的时候,如果只是进行增量升级,即保持主版本号不变,只改变次版本号或发布版本号,那么我们可以直接将新版的共享库替换掉旧版,并且修改SO-NAME的软链接指向新版本共享库,即可实现升级;由于全局符号介入这个机制的存在,LD_PRELOAD里面指定的共享库或目标文件中的全局符号就会覆盖后面加载的同名全局符号,这使得我们可以很方便地做到改写标准C库中的某个或某几个函数而不影响其它函数,对于程序的调试或测试非常有用。

2022-09-01 19:50:13 647

原创 Vim使用(一)——常用技巧及快捷键总结

普通用户的vim配置在。```shellset mouse-=asyntax on "语法高亮set nocompatible "去除VI一致性,必须要添加set nu "显示行号set autowrite "自动保存set ruler "打开状态栏标尺set cursorline "突出显示当前行set smartindent "开

2022-08-18 21:07:11 1033

原创 链接装载与库:第七章——动态链接

将程序的模块互相分割开,不让它们静态地链接在一起;即不对那些组成程序的目标文件进行链接,等到程序运行时再链接。有如Program1和Program2两个程序,并假定保留了Program1.o、Program2.o和Lib.o三个文件。当我们需要运行Program1这个程序时,系统首先加载 Program1.o,而系统发现Program1.o中用到了Lib.o,即Program1.o依赖于Lib.o,此时系统加载Lib.o,并将其加载至内存。所有需要的目标文件加载完毕后,若依赖关系满足,即所有的依赖文件都在磁

2022-08-16 08:49:39 3573 2

原创 链接装载与库:第六章——可执行文件的装载与进程

当linux系统在bash下输入一个命令执行ELF的时候。首先在用户层面,bash进程会调用fork系统调用创建一个新的进程,然后新的进程调用execve系统调用执行指定的ELF文件。原先的bash进程继续返回等待刚才启动的新进程结束,然后继续等待用户输入命令。在进入execve系统调用之后,linux内核就开始进行了真正的装载工作。httpshttpshttpshttpshttpshttps。...............

2022-07-27 13:16:09 554

原创 C/C++获取struct结构体成员的偏移值

可以使用结构体成员的地址减去结构体对象的地址。二、没有结构体对象2.1 使用 0 地址将0强制转换为结构体类型的指针,获取每个成员的地址值,该地址值就是成员的偏移值。,编译器会将当作是一个结构体对象的地址,所以很容易推出成员的偏移值。这种方式在GDB调试core文件时,获取某个结构体成员的偏移值会很方便。2.2 使用offsetof函数标准库中定义了函数offsetof(type,member),该函数是一个宏定义,第一个参数是结构体的类型,第二个参数是所求的成员名。...

2022-06-27 13:18:05 1232

原创 链接装载与库:第四章——静态链接

整个静态链接会使用下面两个源代码例子来展开分析,使用将源文件分别编译成目标文件和。一、空间与地址分配对于链接器来说,整个链接过程中,它就是将几个输入目标文件加工后合并成一个输出文件。在这里输入的目标文件是和,输出文件是可执行文件。可执行文件中的代码段和数据段都是由输入的目标文件合并而来的。对于多个输入目标文件,链接器如何将它们的各个段合并到输出文件?一个最简单的方案就是将输入的目标文件按照次序叠加起来,如下图所示:直接将各个目标文件依次合并。但是这样做会造成一个问题,在有很多输入文件的情况下,输出文件

2022-06-21 13:14:40 774

原创 链接装载与库:第三章——ELF文件结构

一、目标文件的格式目标文件就是源代码编译后但未进行链接的那些中间文件(Windows的.obj和Linux的.o),它跟可执行文件的内容与结构很相似,所以一般跟可执行文件格式一起采用一种格式存储。从广义上看,目标文件与可执行文件的格式其实几乎是一样的,所以我们可以广义地将目标文件与可执行文件看成是一种类型的文件。在Windows下,它们存储格式是PE-COFF文件格式。在Linux下,它们存储格式是ELF文件格式。Linux下符合ELF格式的文件主要有四种:可重定位文件、可执行文件、共享目标文件、核心转

2022-05-19 20:54:35 2019

原创 常见CPU指令系统

文章目录一、指令系统简介二、指令系统组成2.1 地址空间2.2 操作数2.3 指令操作和编码三、RAISC指令比较3.1 指令格式比较3.2 寻址方式比较3.3 公共指令功能3.4 不同指令系统的特色一、指令系统简介依据指令长度的不同,指令系统可分为复杂指令系统(Complex Instruction Set Computer,简称CISC)、精简指令系统(Reduced Instruction Set Computer,简称RISC)和超长指令字(Very Long Instruction Word,

2022-04-18 19:30:21 8692

原创 编译器设计(七)——过程抽象

文章目录一、过程调用二、运行时结构2.1 支持类Algol语言的运行时结构2.2 支持面向对象语言的运行时结构三、过程之间值的传递3.1 传递参数3.2 返回值3.3 确定可寻地址四、标准化链接五、高级主题5.1 堆的显示管理5.2 隐式释放一、过程调用在编译器为调用和返回生成代码时,代码中必须保留足够的信息,确保调用和返回能够正确地运转。如下图所示,在Foe调用Fum时,编译器针对调用生成的代码必须记录Foe中的地址,Fum执行完毕后将控 制返回到该地址。Fum可能因为运行时错误、无限循环或其调用的另

2022-04-15 23:15:19 593

原创 LuaJIT源码结构梳理

5、Bytecode相关的一些定义和操作,定义bc指令格式,bc的dump、read以及write操作。dispatch是跟Bytecode对应的函数相关的一个结构,也是一个很重要的内容,后续会专门讲解。4、IR汇编器,JIT模式下IR到各种目标机器码的映射(SSA IR -> machine code),如果要支持一个新的架构,这块内容是移植的重点。如果要支持一个新的架构,这块内容也是移植的重点。15、Trace记录器(bytecode -> SSA IR),这块内容还是很重要的,基本都是要掌握的。

2022-04-15 11:39:35 1916 14

原创 多发射动态调度流水线

文章目录一、提高流水线执行效率二、多发射数据通路三、动态调度一、提高流水线执行效率看懂这一章节的前提是,掌握经典的单发射五级流水线原理,《深入理解计算机系统》第四章中有详细的讲解,配合《计算机体系结构基础》第3版一起食用,读CSAPP第四章节时做的笔记:CSAPP:第四章——处理器体系结构(上)CSAPP:第四章——处理器体系结构(下)我们通常以应用的执行时间来衡量一款处理器的性能,应用的执行时间 = 指令数 * CPI(Cycles Per Instruction,每指令执行周期数) * 时

2022-04-14 13:17:12 2982 2

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除