自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(81)
  • 资源 (7)
  • 收藏
  • 关注

原创 LLVM 寄存器分配

基本寄存器分配器是四种寄存器分配器中最简单的寄存器分配pass实现(<llvm_root/livm/lib/CodeGen/RegAllocBasic.cpp>)但麻雀虽小,五脏俱全,基本寄存器分配器中实现了根据溢出权重确实虚拟寄存器优先级、按优先级分配物理寄存器,以及物理寄存器不足时将虚拟寄存器溢出到内存等功能。因此,基本寄存器分配器非常适合作为自定义寄存器分配器实现参考LLVM3.0 之前的默认寄存器分配器是线性扫描分配器。

2024-08-11 10:48:23 314

原创 静态分析: 代码优化

Backward Analysis”或“反向分析”是一种分析技术,它从程序或代码的输出结果开始,逆向推导出程序的状态或者输入值这里的表达式“IN[s]=fs(OUT[s])”可以被解读为:给定一个状态s的输出OUT[s],通过某个函数fs来推导出该状态的输入IN[s]Reaching Definitions Analysis 是一种数据流分析技术,用于确定程序中某个变量定义对程序中其他点的可见性。

2024-07-27 10:40:11 636

原创 CPU 流水线相关情况

流水线中经常有一些被称为"相关"的情况发生,它使得指令序列中下一条无法按照设计的时钟周期执行,这些“相关”会降低流水线的性能流水线中的相关分为以下三种类型:结构相关、数据相关、控制相关。

2024-07-21 23:13:53 602

原创 长模式下的分页

长模式下的 4KB 分页下,由一个顶层目录、二级中间层目录和一层页表组成了 64 位地址翻译过程顶级页目录项指向页目录指针页,页目录指针项指向页目录页,页目录项指向页表页,页表项指向一个 4KB 大小的物理页各级页目录项中和页表项中依然存在各种属性位,这在图中已经说明其中的 XD 位,可以控制代码页面是否能够运行上图中没有了页表项,取而代之的是,页目录项中直接存放了 2MB 物理页基地址由于物理页始终 2MB 对齐,所以其地址的低 21 位为 0,用于存放页面属性位。

2024-07-21 15:25:47 355

原创 保护模式下的分页

页目录项、页表项都是 4 字节 32 位,1024 个项正好是 4KB(一个页),因此它们的地址始终是 4KB 对齐的低 12 位才可以另作它用,形成了页面的相关属性,如是否存在、是否可读可写、是用户页还是内核页、是否已写入、是否已访问等4MB 大小的页面下,页表项还是 4 字节 32 位,但只需要用高 10 位来保存物理页面的基地址就可以因为每个物理页面都是 4MB,所以低 22 位始终为 0。

2024-07-21 15:24:13 313

原创 MMU(内存管理单元)

它描述了虚拟地址到物理地址的转换关系,也可以说是虚拟页到物理页的映射关系,所以称为页表。

2024-07-21 15:22:53 390

原创 简单页表和多级页表

同样一个虚拟内存地址,偏移量的部分和上面简单页表一样不变,但是原先的页号部分,把它拆成四段,从高到低,分成4级到1级。以一个页的大小是4K字节(4KB)为例,我们需要20位的高位,12位的低位。因为虚拟内存地址分布的连续性,树的第一层节点的指针,很多就是空的,也就是不需要对应对应的子树。做地址转换的页表,只需要保留虚拟内存地址的页号和物理内存地址的页号之间的映射关系即可。找到最终最终的物理页号,就好像通过一个特定的访问路径,走到树最底层的叶子节点。所谓不需要子树,其实就是不需要对应的2级,3级的页表。

2024-07-21 15:19:11 802

原创 CPU工作模式-长模式

保护模式下为了实现对中断进行权限检查,实现了中断门描述符,在中断门描述符中存放了对应的段选择子和其段内偏移,还有 DPL 权限如果权限检查通过,则用对应的段选择子和其段内偏移装载 CS:EIP 寄存器从实模式直接切换到长模式,也可以从保护模式切换长模式切换到长模式和切换保护模式的流程差不多,只是需要准备的段描述符有所区别,还有就是要注意同时开启保护模式和分页模式。

2024-07-21 15:17:17 266

原创 CPU工作模式- 保护模式

因为实模式下CPU不需要做权限检查,所以它可以直接中断向量表中的值装载CS:IP寄存器x86 CPU在第一次加电和每次reset后,都会自动进入实模式,想要进入保护模式,就需要程序员写代码实现从实模式切换到保护模式接下来,CPU 发现了 CRO 寄存器第 0 位的值是 1就会按 GDTR 的指示找到全局描述符表,然后根据索引值 8,把新的段描述符信息加载到 CS 影子寄存器,当然这里的前提是进行一系列合法的检查CPU 真正进入了保护模式,CPU 也有了 32 位的处理能力。

2024-07-21 15:16:20 815

原创 CPU工作模式- 实模式

地址模式。

2024-07-21 15:14:42 396

原创 指令重排序

CPU由多个功能部件构成在这个结构中,一条指令执行时,要依次用到多个功能部件,分成多个阶段,虽然每条指令是顺序执行的,但每个部件的工作完成以后,就可以服务于下一条指令,从而达到并行的效果这种结构叫做。

2024-07-20 07:42:45 1354

原创 Verilog HDL 基本概念

(1) 等式运算符中的"" 与 "=" 的区别是: 对于"“运算,参与比较的两个操作数必须逐位相等,其结果才为1,如果某些值是不定态X或高阻态Z,那么得到的结果是不定值X;而对于”="运算,则要求对参与的操作数中为不定态X或高阻态Z的位与进行比较,两个操作数也必须完全一致,其结果才为1,否则结果为0针对上面的 a、b,"ab"的返回结果为X,而"a=b"的返回结果为1。

2024-07-18 07:19:38 1076

原创 对数的基本概念

特别地,我们称以10为底的对数叫做常用对数(common logarithm),并记为lg称以无理数e(e=2.71828…)为底的对数称为自然对数(natural logarithm),并记为ln零没有对数在实数范围内,负数无对数。[3] 在虚数范围内,负数是有对数的。

2024-07-14 22:08:03 196

原创 TCP中的拥塞控制

这两个结合起来就是AIMD算法,是使用最广泛的算法。拥塞避免算法不能够完全避免网络拥塞,通过控制拥塞窗口的大小只能使网络不易出现拥塞。

2024-07-14 22:04:40 795

原创 乘法器的基本操作

乘法因为只有“0”和“1”两种情况,所以可以做成输入输出都是 4 个开关,中间用 1 个开关,同时来控制这 8 个开关的方式,这就实现了二进制下的单位的乘法。这样,乘数和被乘数就像两列相向而驶的列车,仅仅需要简单的加法器、一个可以左移一位的电路和一个右移一位的电路,就能完成整个乘法。在展开之后呢,我们可以把原来需要较少的,但是有较多层前后计算依赖关系的门电路,展开成需要较多的,但是依赖关系更少的门电路。然后,把被乘数左移一位,把乘数右移一位,仍然用乘数去乘以被乘数,然后把结果加到刚才的结果上。

2024-07-14 16:45:10 690

原创 建立数据通路(三)

同样通过译码器,找出我们期望执行的指令,也就是在之前讲到过的opcode,以及后面对应的操作数或者寄存器地址,只是,这样的“译码器”,比如2-1选择器和3-8译码器,要复杂得多。这个自动计数器,可以拿来当PC寄存器,事实上,PC寄存器的这个PC,英文就是Program Counter,也就是。通过控制反相器的输入是0还是1,能够给决定对应的输出信号,是和地址A,还是地址B的输入信号一致。其实,译码器的本质,就是从输入的多个位的信号中,根据一定的开关和电路组合,选择出自己想要的信号。

2024-07-14 16:42:06 873

原创 建立数据通路 (二)

一个 D 型触发器,只能控制 1 个比特的读写,但是如果我们同时拿出多个 D 型触发器并列在一起,并且把用同一个 CLK 信号控制作为所有 D 型触发器的开关,这就变成了一个 N 位的 D 型触发器,也就可以同时控制 N 位的读写。实现这样一个电路,通过电的磁效应产生开关信号的方法是一样的,只不过,这里的磁性开关,打开的不再是后续的线路,而是当前线路。当我们把A前面的开关R合上的时候,A的输入变成了1和0,输出就变成了0,对应B的输入变成0,0,输出变成1。一个开关A,一开始是断开的,有手工控制。

2024-07-14 16:40:41 852

原创 寄存器分配

寄存器位于CPU 或 GPU内部的少量高速存储器,通常用于保存机器指令的操作数由于其价格昂贵,导致其数量有限,又由于存储速度快,使其不可或缺。因此,寄存器是计算机体系结构中的关键资源之一。在计算复杂表达式的过程中产生的中间结果都保存在寄存器中,更复杂的编译器会将经常使用的变量也保存在寄存器中,以避免反复存取如果是优化的编译器,还会将公共子表达式消除或者将循环不变量移动以后的重用值保存在寄存器中开发者在编写高级语言程序时会用到变量定义,如 int x, string y 等。

2024-07-13 21:26:13 1063

原创 调度pass的定制

作为调度pass实现类,MachineScheduler 和 PostMachineScheduler 的优点之一是允许开发者在LLVM 已有调度算法和策略基础上做不同的定制化。

2024-07-08 23:24:56 944

原创 关联(Association) && 聚合(Aggregation) && 组合(Composition)

要符合聚合条件,整个对象及其各个部件必须具有以下关系该部件(成员)是对象(类)的一部分该部件 (成员) 一次可以属于多个对象(类)该部件 (成员)的存在不由对象(类)管理该部件(成员)不知道对象(类)的存在像组合一样,聚合仍然是部件与整体的关系,其中部件包含在整体中,并且是单向关系,但是与组合不同,部件一次可以属于一个以上的对象,而整个对象对部件的存在和生命周期不负责创建聚合时,聚合不负责创建部件,销毁聚合时,聚合不负责销毁部件例如,考虑一个人与其家庭住址之间的关系。

2024-07-07 08:59:37 782

原创 建立数据通路(一)

之前说过,现在的Intel CPU 支持 2000 个以上的指令,意味着,控制器输出的控制信号,至少有2000种不同的组合。取出指令至少需要一个CPU周期,执行至少也需要CPU周期,复杂的指令则需要更多的CPU周期。控制器"翻译"出来的,就是不同的控制信号,这些控制信号,告诉ALU去做不同的计算。所以,我们说一个指令周期,包含多个CPU周期,而一个CPU周期包含多个时钟周期。一方面,所有CPU支持的指令,都会在控制器里面,被解析成不同的输出信号。操作的,指令的解码过程,也是由。里面完成,不需要用到运算器。

2024-07-05 23:12:21 927

原创 加法器的基本操作

然后,把这个加和后的结果Y,和个位相加后输出的进位信息U,再连接到一个半加器上,就会再拿到一个是否进位的信息V和对应的加和后的结果W。把两个半机器的进位输出,作为一个或门的输入连接起来,只要两次加法中任何一次需要进位,那么二位上,就会向左侧的四位进一位。第一个半加器,用和个位的加法一样的方式,得到是否进位X和对应的二个数相加后的结果Y,这样两个输出。因为一共只有三个bit相加,即使3bit都是,也最多进一位。

2024-07-05 23:10:05 300

原创 可编程定时计数器8253/8254 - 8253入门

在计算机系统中,为了使所有设备之间的通信井然有序,各通信设备间必须有统一的节奏,不能各干各的,这个节奏就被称为定时或时钟时钟并不是计算机处理速度的衡量,而是一种使设备间相互配合而避免发生冲突的节拍。时钟只是一种时间的度量,只是一种节奏,其时间长度并不统一,各种设备都有自己的时钟,也就是有自己的工作节拍时钟信号并不是专指处理器的时钟,也并不特指IRQ0上的时钟,表达的意思仅仅是设备自己的工作节拍、频率。

2024-06-30 21:03:21 740

原创 可编程定时计数器8253/8254 - 8253控制字

8253 的目的就是为了提升时钟中断信号的频率,而时钟中断信号是由计数器 0 负责产生的其实这是利用了分频器的原理,将高频的输入脉冲信号 CLK 转换为低频的输出信号 OUT,此信号就是时钟中断信号这与计数器的工作方式有关,您已经知道了,并不是所有的工作方式都能让计数器周期性地发出中断信号,假设计数器。工作在方式 2 下,下面介绍下中断信号产生的原理CLK 引脚上的时钟脉冲信号是计数器的工作频率节拍,三个计数器的工作频率均是 1.19318MHZ,即一秒内会有 1193180 次脉冲信号。

2024-06-30 17:27:08 675

原创 Go线程调度器-启用或停止M

stopm(): 停止当前M的执行,直到因有新的G变得可运行而被唤醒gcstopm(): 为串行运行时任务的执行让路,停止当前M的执行。串行运行时任务执行完毕后会被唤醒stoplockedm(): 停止已与某个G锁定的当前M的执行,直到因这个G变得可运行的而被唤醒startlockedm(gp *g): 唤醒与gp锁定的那个M,并让该M去执行gpstartm(_p_ *p, spinning bool): 唤醒或创建一个M去关联_p_并开始执行。

2024-06-30 17:23:54 304

原创 Go线程调度器

字段gcwaiting、stopwait和stopnoted都是串行运行时任务执行前后的辅助协调手段gcwaiting字段的值用于表示是否需要停止调度字段sysmonwait和sysmonnote与前面那一组字段的用户类似,只不过它们针对的是系统监测任务系统监测任务是持续执行的,更准确地说,它处在无尽的循环之中。在每次迭代之初,系统监测程序都会先检查调度情况。

2024-06-30 17:22:44 476

原创 Go线程实现模型-核心元素的容器

3个全局容器存在的主要目的,都是为了罗列某个核心元素的全部。

2024-06-30 17:21:12 252

原创 Go线程实现模型-G

一个G就代表一个goroutine(或称Go例程),也与go函数相对应。作为编程人员,我们只是使用go语句向Go的运行时系统提交一个并发任务,而Go的运行时系统则会按照我们要求并发地执行它Go编译器会把go语句变成对内部函数newproc的调用,并把go函数及其参数都作为参数传递给这个函数。

2024-06-30 17:20:28 449

原创 Go线程实现模型-P

在P的结构中,可运行G队列和自由G列表最重要的两个成员。至少对于Go语言的是这样,它们间接地体现了运行时系统对G的调度情况。

2024-06-30 17:19:57 492

原创 Go线程实现模型-主框架、M

一个M代表了一个内核线程。在大多数情况下,创建一个M,都是由于没有足够的M来关联P并运行其中可运行的G不过,在运行时系统执行系统监控或垃圾回收等任务的时候,也会导致新M的创建。

2024-06-30 17:19:23 441

原创 线程实现模型

此模型下的线程是由用户级别的线程库全权管理的线程库并不是内核的一部分,而只是存储在进程的用户空间之中,这些线程的存在在对于内核来说是无法感知的应用程序在对线程进行创建、终止、切换或同步等操作的时候, 并不需要让CPU从用户切换到内核态并且,由于对线程的管理完全不需要内核的参与,导致在此模型下并不能够真正并发运行在调度器的眼里,进程是一个无法再被分割的调度单元,无论其中存在多少个线程。

2024-06-30 17:18:28 263

原创 线程的调度

一些线程需要花费一定的时间使用CPU进行计算,而另外一些线程则会花费一些时间等待相对较慢的I/O操作的完成一个用于计算16位整数的14次方根的线程属于前者,而一个等待人类用户通过敲击键盘提供输入数据的线程则属于后者调度器会依据它对线程的趋向性的猜测把它们分类,并让I/O受限的线程具有更高的动态优先级以优先使用CPU。因为IO操作往往会花费更长时间,应该让它们尽早开始。

2024-06-30 17:17:52 497

原创 CPU架构

一个CPU处理器中一般有多个运行核心,我们把一个运行核心称为一个物理核,每个物理核都可以运行应用程序每个物理核都拥有私有的一级缓存(Level 1 Cache,简称L1 Cache), 包括一级指令缓存和一级数据缓存,以及私有的2级别缓存(L2 Cache)物理核的私有缓存,指的是缓存空间只能被当前的这个物理核使用,其他的物理核无法对这个核的缓存空间进行数据存取。

2024-06-30 17:15:44 586

原创 LLVM 中的指令调度器及其工作过程

这三类调度器都有llc命令行选项可以控制其使能或禁用在寄存器分配前,基本块中的操作数仍以虚拟寄存器表示,约束较少,指令调度的自由度较高,但要考虑调度结果对寄存器分配的影响。例如,如果虚拟寄存器的定值和使用相距较远,虚拟寄存器的生存期可能较长,这会增加寄存器分配的难度如果能通过指令重排序,拉近虚拟寄存器的定值和使用之间的距离,可以使寄存器分配难度降低自底向上策略较为简单,并且这种策略已有很多成熟编译时优化。双向调度策略,即自顶向下、自底向上同时进行,再从中选出最好的候选指令。

2024-06-30 16:03:16 881

原创 指令调度基本概念

为了提高处理器执行指令的并行度,处理器将计算机指令处理过程拆分为多个阶段,并通过多个硬件处理单元,将不同指令处理的前后阶段重叠并行执行,形成流水线(pipeline)处理器的流水线结构是处理器微架构最基本的要素,对处理器微架构的其他方面有重要影响。典型的MIPS处理器5级流水线包括取指、译码、执行、访存和写回首先,在取指阶段,指令被从内存中读出。然后,在译码阶段得到指令需要的操作数寄存器索引,并通过索引从通用寄存器中将操作数读出。

2024-06-23 21:56:21 982

原创 Redis 高性能基本操作

单元素操作是基础单元素操作,是指每一种集合类型对单个数据实现增删改查例如,Hash 类型的 HGET、HSET 和 HDEL,Set 类型的 SADD、SREM、SRANDMEMBER 等这些操作的复杂度由集合采用的数据结构决定,例如,HGET、HSET 和 HDEL 是对哈希表做操作,所以它们的复杂度都是 O(1)Set 类型用哈希表作为底层数据结构时,它的 SADD、SREM、SRANDMEMBER 复杂度也是 O(1)注意点集合类型支持同时对多个元素进行增删改查,例如 Hash 类型

2024-06-23 08:44:58 781

原创 hadoop Yarn资源调度器

Yarn是一个资源调度平台,负责为运算程序提供服务器资源,相当于一个分布式的操作系统平台,而MapReduce等运算程序相当于操作系统之上的应用程序。

2024-06-19 22:30:59 1082

原创 全局指令选择

虽然LLVM 已经实现全局指令选择,但若要在llc中启用全局指令选择,还需在llc命令中增加-global-isel选项另一个和全局指令选择相关的llc命令行选项是-global-isel-abort. 当该选项值为0时,llc会在全局指令选择方法失败时,将SelectionDAG指令选择方法为回退方法。当该选项值为1时,llc会在全局指令选择方法失败时直接报错。

2024-06-18 23:48:34 803

原创 指令选择原理与实现方式

编译器前端将源代码转换为等效形式的IR,IR经过优化器优化后传递到后端,由代码生成器将IR 代码转换为汇编代码或目标代码在这个过程中,后端首先通过指令选择器目标机器支持的指令来实现IR指令至于指令的顺序,可由后续的指令调度器决定。

2024-06-17 07:39:22 1186

原创 LLVM 中 的 pass 及其管理机制

在编译器开发时,可以混合使用两种方式,将各种pass组合为流水线,对IR做不同的处理和优化LLVM Pass 类及其子类的继承关系如下图所示。

2024-06-16 23:21:50 1146

C/C++ 一致性hash算法

一致性hash算法

2021-04-09

C/C++ 霍夫曼编码案例

霍夫曼编码

2021-04-09

C/C++ 高性能定时器应用

高性能定时器应用

2021-04-09

C/C++ 通过最大堆求topk

通过最大堆求topk

2021-04-09

C/C++ 求中位数的值

求中位数的值

2021-04-09

mergeSamilFile.zip

合并有序小文件

2021-04-09

bigFileTopN.zip

大文件关键字统计

2021-04-09

空空如也

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

TA关注的人

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