自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Word2vec Skip-Gram 模型

在Skip-Gram 模型中,存在两个权重矩阵。输入层到隐藏层的矩阵W和隐藏层到输出层的矩阵W’. 这个两个矩阵分别对应词向量的输入和输出表示。

2025-02-11 22:16:05 652

原创 数值型特征处理 - 归一化和分桶

将连续数值离散化为区间(桶),捕捉非线性关系或减少噪声影响,常用于树模型或逻辑回归。

2025-02-09 17:23:27 732

原创 拓扑 排序

拓扑排序是一种重要的图算法,适用于解决依赖关系问题。通过C++实现,可以清晰地理解其工作原理和实现细节。

2025-02-09 17:20:46 141

原创 Spark RDD

RDD是一种抽象,是Spark对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体。

2024-10-26 22:28:18 1265

原创 Spark 基础操作

用于RDD创建工作。RDD创建只有两种方法,一种是来自于内存集合和外部存储系统,另一种是通过转换操作生成的RDD。

2024-10-26 22:27:45 934

原创 定义类与类之间的交互关系

泛化(Generalization)概念可以简单理解为继承关系代码实现public class A { ... }public class B extends A { ... }实现(Realization)概念一般是指接口和实现类之间的关系代码实现public interface A {...}public class B implements A { ... }聚合(Aggregation)概念聚合是一种包含关系,A类对象包含B类对象,B类对象的生

2024-10-23 10:46:32 573

原创 改善代码质量的20条编程规范

代码嵌套层次过深往往是因为 if-else、switch-case、for 循环过度嵌套导致的个人建议,嵌套最好不超过两层,超过两层之后就要思考一下是否可以减少嵌套过深的嵌套本身理解起来就比较费劲嵌套过深很容易因为代码多次缩进,导致嵌套内部的语句超过一行的长度而折成两行,影响代码的整洁。

2024-10-23 10:44:03 719

原创 染色算法的简单概述

这句话描述的是一种用于确定寄存器分配的染色算法在这个上下文中,我们有一个图,图的节点代表变量,边代表变量之间的干扰(即两个变量不能共享同一个寄存器)算法的目标的是为了判断给定的k个寄存器是否足够给所有的变量分配如果一个图可以用k种颜色来染色(即每个节点可以用一个颜色表示,且相邻的节点颜色不同),那么添加一个边数少于k的节点,仍然可以用k种颜色来颜色。因为新节点的边数少于k,所以至少有一种颜色是没有被它的任何邻居使用的。

2024-09-22 11:03:23 492

原创 LLVM 中的Value、User、Use设计

首先,定义一个简单的LLVM IR 代码片段,这里创建一个简单的加法操作在这个例子中,%1是一个Value,它代表了加法操作的结果.i32 是它类型,表示这是一个32位的整数10 和 20 是操作数,它们也是Value。

2024-09-21 22:47:57 1391

原创 LLVM 寄存器分配

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

2024-08-11 10:48:23 694

原创 静态分析: 代码优化

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

2024-07-27 10:40:11 856

原创 CPU 流水线相关情况

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

2024-07-21 23:13:53 707

原创 长模式下的分页

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

2024-07-21 15:25:47 403

原创 保护模式下的分页

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

2024-07-21 15:24:13 344

原创 MMU(内存管理单元)

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

2024-07-21 15:22:53 504

原创 简单页表和多级页表

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

2024-07-21 15:19:11 951

原创 CPU工作模式-长模式

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

2024-07-21 15:17:17 410

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

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

2024-07-21 15:16:20 1008

原创 CPU工作模式- 实模式

地址模式。

2024-07-21 15:14:42 440

原创 指令重排序

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

2024-07-20 07:42:45 1521

原创 Verilog HDL 基本概念

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

2024-07-18 07:19:38 1364

原创 对数的基本概念

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

2024-07-14 22:08:03 668

原创 TCP中的拥塞控制

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

2024-07-14 22:04:40 846

原创 乘法器的基本操作

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

2024-07-14 16:45:10 795

原创 建立数据通路(三)

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

2024-07-14 16:42:06 910

原创 建立数据通路 (二)

一个 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 901

原创 寄存器分配

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

2024-07-13 21:26:13 1212

原创 调度pass的定制

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

2024-07-08 23:24:56 991

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

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

2024-07-07 08:59:37 1231

原创 建立数据通路(一)

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

2024-07-05 23:12:21 976

原创 加法器的基本操作

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

2024-07-05 23:10:05 373

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

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

2024-06-30 21:03:21 1140

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

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

2024-06-30 17:27:08 2058

原创 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 363

原创 Go线程调度器

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

2024-06-30 17:22:44 546

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

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

2024-06-30 17:21:12 267

原创 Go线程实现模型-G

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

2024-06-30 17:20:28 471

原创 Go线程实现模型-P

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

2024-06-30 17:19:57 510

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

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

2024-06-30 17:19:23 474

原创 线程实现模型

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

2024-06-30 17:18:28 286

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关注的人

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