香山南湖架构分析--FE

news2024/11/20 7:25:49

总体架构

  • 分支预测和指令缓存,通过FTQ达到解耦的目的;
  • FTQ将请求送给ICache,进行取指;
  • 取出的指令码通过预译码初步检查分支预测的错误并及时冲刷预测流水线;
  • 检查后的指令送入指令缓冲并传给译码模块,最终形成后端的指令供给;

分支预测

 

分支预测单元采用一种多级混合预测的架构,主要包括:

  •  下一行预测器(Next Line Predictor,以下简称 NLP)
    • 由uBTB组成;
    • 提供无bubble的预测,在预测请求的下一拍,就能得到结果;
  •  精确预测器(Accurate Predictor,以下简称 APD)
    • 由 FTB、TAGE-SC、ITTAGE、RAS 组成;
    • 其中,FTB、TAGE、RAS 的延迟为 2 拍;
    • SC、ITTAGE 的延迟为 3 拍;

一次预测会经历三个流水级,每一个流水级都会产生新的预测内容。这些分布于不同流水级的预测器组成了一个覆盖预测器 (overriding predictor)。

相较于上一代雁栖湖架构,分支预测器的最大区别在于预测块的定义方式。

  • 南湖架构中,BTB 被替换成了 FTB (Fetch Target Buffer),每一个 FTB 项都形成一个预测块。
  • 我们不仅对下一个块的起始地址做预测,同时也对当前块的结束点做预测。

顶层逻辑

负责预测逻辑和流水线握手逻辑,以及全局分支历史的管理。

与FTQ的交互

  • 各级流水线都会连接FTQ
  • 当第一个预测流水线,预测出了结果,或者后续的流水线,发现预测结果与之前的不一致,和FTQ的握手vld会拉高,将预测信息写入或者进行修改;

全局分支历史管理

南湖架构实现了接近完全准确的全局分支历史

  • speculative update
    • 每次预测,都会根据预测块内部的分支指令个数,以及预测方向,计算新的全局历史,并将其用在新的预测中;
  • 覆盖逻辑中加入全局历史的比较
    • 一旦位于后面的流水级推测更新后,与之前的流水线结果不同时(条件分支个数,或者时执行的结果不同),会flush流水线(?),重新开始预测;
  • 预测后存储全局历史的副本
    • 在预测结束后,当次预测使用的全局历史会存储到 FTQ 中,在误预测恢复时读出并送回 BPU

之所以说“接近”完全准确,是因为 BPU 会忽略那些从未跳转的条件分支指令,它们不会被记录在 FTB 中,也就不会包含在分支历史里;

下一行预测器 (NLP)

旨在用较小的存储开销提供一个无空泡的快速预测流。

它的功能主要由 uBTB 提供。

对于给定的起始地址 PC,uBTB对从 PC 开始的一个预测块做出整体预测。

NLP

  • 用分支历史和 PC 的低位异或索引存储表;
  • 从表中读出的内容直接提供了最精简的预测:
    • 下一个预测块的起始地址 nextAddr;
    • 这个预测块是否发生分支指令跳转 taken;
    • 跳转指令相对起始地址的偏移 cfiOffset;
    • 是否在条件分支跳转 takenOnBr;
    • 块内包含分支指令的数目 brNumOH;
    • 另外还提供分支指令的相关信息以更新分支历史;
  • 我们摒弃了 tag 匹配的做法,这会带来一个问题:
    • 在有 tag 匹配的情况下,如果一个预测块没有命中,会将下一个预测块的 PC 置为当前 PC 加预测宽度;
    • 通常,为了避免浪费,如果在预测块中没有分支指令,则训练时不会写入 uBTB。
    • 在这个前提下,如果没有 tag 匹配机制,则很容易把没有分支指令(在 tag 匹配机制下不命中)的预测块预测为另一个跳转的块。
      • 针对这种情况,我们引入了另一种预测机制:对当前 PC 是否可能存在有效的分支指令进行预测;
      • 这个预测机制的存储结构由取指 PC 直接索引,它的查询结果表示了该取指 PC 是否被写入过。
      • 在它指示该 PC 没被写入过的时候,会把下一个 PC 预测为当前 PC 加预测宽度。

精确预测器 (APD)

为提高总体预测准确率,减少预测错误带来的流水线冲刷,南湖架构实现了延迟更高,同时也更为精确的预测机制。

精确预测器包括取指目标缓冲 FTB、条件分支方向预测器 TAGE-SC、间接跳转预测器 ITTAGE 和返回地址栈 RAS。

FTB

  • FTB 是 APD 的核心。
  • APD 的其他预测部件所作出的预测全部依赖于 FTB 提供的信息。
  • FTB 除了提供预测块内分支指令的信息之外,还提供预测块的结束地址
  • 对于 FTB 来说,FTB 项的生成策略至关重要。
  • 记 FTB 项的起始地址为 start,结束地址为 end,具体策略如下:
    • FTB 项由 start 索引,start 在预测流水线中生成,实际上,start 基本遵循如下原则之一:
      • start 是上一个预测块的 end
      • start 是来自 BPU 外部的重定向的目标地址;
    • FTB项内最多记录两条分支指令,其中第一条一定是条件分支;
    • end 一定满足三种条件之一:
      • end - start = 预测宽度
      • end 是从 start 开始的预测宽度范围内第三条分支指令的 PC
      • end 是一条无条件跳转分支的下一条指令的 PC,同时它在从 start 开始的预测宽度范围内;
    • 注意:这种训练策略下,同一条分支指令可能存在于多个 FTB 项内。
  • 和论文中的实现一样,我们只存储结束地址的低位,而高位用起始地址的高位拼接得到;
  • 论文链接:A ScalableFront-EndArchitectureforFastInstructionDeliveryicon-default.png?t=O83Ahttps://download.csdn.net/download/zhangshangjie1/89865369
  • 和 AMD的做法相似,我们还对 FTB 项中的条件分支指令记录“总是跳转”位;
    • 该位在第一次遇到该条件分支跳转时置 1,在它值为 1 的时候,该条件分支的方向总是预测为跳转,也不用它的结果训练条件分支方向预测器;
    • 当该条件分支遇到一次执行结果为不跳转的时候,将该位置 0,之后它的方向由条件分支方向预测器预测。

TAGE-SC

TAGE-SC 是南湖架构条件分支的主预测器,它的大致逻辑继承自上一代雁栖湖架构的 TAGE-SC-L。

目前的实现中,TAGE 的延迟是 2 拍,SC 的延迟是 3 拍。

TAGE 利用历史长度呈几何级数增加的多个预测表,可以挖掘极长的分支历史信息。它的基本逻辑如上图所示。

  • 由一个基预测表和多个历史表组成,基预测表用 PC 索引
  • 而历史表用 PC 和一定长度的分支历史折叠后的结果异或索引,不同历史表使用的分支历史长度呈几何级数关系。
  • 在预测时,还会用 PC 和每个历史表对应的分支历史的另一种折叠结果异或计算 tag,与表中读出的 tag 进行匹配:
    • 如果匹配成功则该表命中;
    • 最终的结果取决于命中的历史长度最长的预测表的结果;
  • 在南湖架构中,每次预测最多同时预测 2 条条件分支指令。
    • 在访问 TAGE 的各个历史表时,用预测块的起始地址作为 PC,同时取出两个预测结果
    • 它们所用的分支历史也是相同的。

  • TAGE还有一些其他的特性,如备选预测逻辑,useful域段,sc校正等功能,这些功能参考:TAGE predictor

ITTAGE

  • RISC-V 指令集中 jalr 指令支持以寄存器取值加一立即数的方式指定无条件跳转指令目标地址。
  • 不同于在指令中直接编码跳转偏移量的 jal 指令,jalr 的跳转地址需要借助寄存器访问间接获取,因而被称为间接跳转指令。
  • 由于寄存器的值可变,于是相同 jalr 指令的跳转地址可能很多样,所以 FTB 记录固定地址的机制难于准确预测这种指令的目标地址。
  • 在香山处理器中,jalr 指令的预测机制体现为 FTB,RAS 与 ITTAGE 的协作。
    • FTB 会记载 jalr 指令的最近一次跳转地址,部分 jalr 指令的跳转地址相对固定,仅靠 FTB 就足以达到很高的预测准确率;
    • 函数返回是 jalr 指令中较为常见的应用场景,它和函数调用指令有着显著的配对性,可以使用具有栈结构的 RAS 进行预测;
    • 不符合以上特征的 jalr 指令交由 ITTAGE 预测。

ITTAGE是一种准确率很高的间接跳转预测器,它的基本结构如上图所示。

  • ITTAGE 在 TAGE 的主要区别在于,每个表项在 TAGE 表项的基础上加入了所预测的跳转地址。
  • 由于每个 FTB 项仅存储至多一条间接跳转指令信息,ITTAGE 预测器每周期也最多预测一条间接跳转指令的目标地址。
  • ITTAGE 和 TAGE 的内部逻辑基本相同,此处不再重复。

RAS

RAS 是一个寄存器堆实现的栈存储结构

  • 它对 call 指令的下一条指令的地址进行记录
  • 在 FTB 认为预测块会在 call 指令跳转时压栈
  • 并在 FTB 认为预测块在 ret 指令跳转时弹出。
  • 每一项包含一个地址和一个计数器
    • 当重复压栈同一个地址时,栈指针不变,计数器加一,用于处理程序中递归调用的情况。
    • 每次预测后,栈顶项和栈指针都会存入 FTQ 的存储结构,用于误预测时恢复。

预测器的训练

总的来说,为防止错误执行路径对预测器内容的污染,各部分预测器在预测块的所有指令提交后进行训练。

它们的训练内容来自自身的预测信息和预测块中指令的译码结果和执行结果,它们会被从 FTQ 中读出,并送回 BPU。其中,

  • 自身的预测信息会在预测后打包传进 FTQ 中存储;
  • 指令的译码结果来自 IFU 的预译码模块,在取到指令后写回 FTQ;
  • 而执行结果来自各个执行单元。

在 BPU 收到来自其外部的重定向请求时,会把曾进行过推测更新的元素(全局历史、RAS 栈顶项等)进行恢复。

预测块 分支预测单元 (BPU) 每次给取指目标队列 (FTQ) 的请求基本单位,它描述了一个取指请求的范围,以及其中分支指令的情况

预测宽度 每次预测提供给取指单元的最大指令流宽度,在南湖架构中与取指宽度相同,都为 32 字节。当 FTB 预测未命中时,目标地址默认为当前地址和预测宽度相加

覆盖预测器 一种多个不同延迟的预测器的组织形式,延迟大的、相对更准确的预测器被放在后面的流水级,其产生的预测结果会与前面的预测器进行比较,如果不同则会冲刷流水线,整体预测结果以最准确的预测器为准

全局分支历史 指令流中所有条件分支指令的执行结果序列,每一条分支指令的执行结果作为一位(0/1)存在于全局分支历史中,一般以移位寄存器的方式实现

备选预测 TAGE 类预测器一种优化,当对长历史预测结果信心不足时选择次长历史下的命中结果作为最终预测,可提升整体预测正确率

取指目标队列 (FTQ)

FTQ 是分支预测和取指单元之间的缓冲队列:

  • 主要职能是暂存 BPU 预测的取指目标,并根据这些取指目标给 IFU 发送取指请求
  • 另一重要职能是暂存 BPU 各个预测器的预测信息,在指令提交后把这些信息送回 BPU 用作预测器的训练,因此它需要维护指令从预测到提交的完整的生命周期
  • 由于后端存储 PC 的开销较大,当后端需要指令 PC 的时候,会到 FTQ 读取。
  • 由于 BPU 基本无阻塞,它经常能走到 IFU 的前面,于是 BPU 提供的这些还没发到 IFU 的取指请求就可以用作指令预取,FTQ 中实现了这部分逻辑,直接给指令缓存发送预取请求

FTQ 是一个队列结构,但队列中每一项的内容是根据其自身特点存储在不同的存储结构中的。这些存储结构主要包括以下几种:

  • ftq_pc_mem: 寄存器堆实现,存储与指令地址相关的信息,包括如下的域

    • startAddr 预测块起始地址
    • nextLineAddr 预测块下一个缓存行的起始地址
    • isNextMask 预测块每一条可能的指令起始位置是否在按预测宽度对齐的下一个区域内
    • fallThruError 预测出的下一个顺序取指地址是否存在错误
  • ftq_pd_mem: 寄存器堆实现,存储取指单元返回的预测块内的各条指令的译码信息,包括如下的域

    • brMask 每条指令是否是条件分支指令
    • jmpInfo 预测块末尾无条件跳转指令的信息,包括它是否存在、是 jal 还是 jalr、是否是 call 或 ret 指令
    • jmpOffset 预测块末尾无条件跳转指令的位置
    • jalTarget 预测块末尾 jal 的跳转地址
    • rvcMask 每条指令是否是压缩指令
  • ftq_redirect_sram: SRAM 实现,存储那些在重定向时需要恢复的预测信息,主要包括和 RAS 和分支历史相关的信息

  • ftq_meta_1r_sram: SRAM 实现,存储其余的 BPU 预测信息

  • ftb_entry_mem: 寄存器堆实现,存储预测时 FTB 项的必要信息,用于提交后训练新的 FTB 项;

指令在 FTQ 中的生存周期

指令以预测块为单位,从 BPU 预测后便送进 FTQ,直到指令所在的预测块中的所有指令全部在后端提交完成,FTQ 才会在存储结构中完全释放该预测块所对应的项。

  • 预测块从 BPU 发出,进入 FTQ,bpuPtr 指针加一,初始化对应 FTQ 项的各种状态,把各种预测信息写入存储结构;如果预测块来自 BPU 覆盖预测逻辑,则恢复 bpuPtr 和 ifuPtr;
  • FTQ 向 IFU 发出取指请求,ifuPtr 指针加一,等待预译码信息写回
  • IFU 写回预译码信息,ifuWbPtr 指针加一,如果预译码检测出了预测错误,则给 BPU 发送相应的重定向请求,恢复 bpuPtr 和 ifuPtr
  • 指令进入后端执行,如果后端检测出了误预测,则通知 FTQ,给 IFU 和 BPU 发送重定向请求,恢复 bpuPtrifuPtr 和 ifuWbPtr
  • 指令在后端提交,通知 FTQ,等 FTQ 项中所有的有效指令都已提交,commPtr 指针加一,从存储结构中读出相应的信息,送给 BPU 进行训练;

预测块 n 内指令的生存周期会涉及到 FTQ 中的 bpuPtrifuPtrifuWbPtr 和 commPtr 四个指针,当 bpuPtr 开始指向 n+1 时,预测块内的指令进入生存周期,当 commPtr 指向 n+1 后,预测块内的指令完成生存周期。

取指令单元(Instruction Fetch Unit)

南湖架构的 IFU 采用了 4 级流水线的结构,相较于雁栖湖版本 IFU 的设计做了非常大的简化,这得益于采用分支预测 - 指令缓存解耦的取指令架构。

一个取指令请求从 FTQ 发出之后在 IFU 中经历了下面几个阶段:

  • 从 FTQ 发送过来的取指令请求包含了一个 32 bytes 指令码 (称为一个指令块 ) 的起始地址和下一个跳转目标的地址,
  • 在 IFU0 阶段同时发送请求给 IFU 流水线和 ICache 模块。
  • IF1 阶段会做一些简单计算(例如这个指令块里每个 2 bytes, 即每一条可能的指令的 PC )。
  • IF2 阶段等到指令缓存返回最多两个 cache line 的数据(因为可能存在这个 指令块 跨行 的情况)之后,第一步先做指令切分,将在取指令地址之外的指令码抛弃得到有效范围的指令码。送入预译码器进行预译码,同时将 16 bits 的压缩指令扩展为 32 bits 的指令。
  • IF3 阶段首先会将预译码结果送到 分支预测检查器 里,发现错误就会在下一拍刷新 IFU 流水线并把信息发送给 FTQ 刷新预测器并重新取指令。未发现错误的缓存在指令缓冲队列(IBuffer)里等待译码。
  • IF3 阶段还会根据地址翻译的结果向指令 MMIO 模块发起取指令请求,同时转变为 MMIO 取指令模式,指令一条一条顺序执行。
  • IFU 控制逻辑还需要 处理半条 RVI 指令 的情况。

预译码

预译码器将经过切分的 16 个 16 bits 指令码进行译码,得到部分指令信息:

  • 是否是跳转指令
  • 跳转指令类型
  • 以及是否是压缩指令等
  • 对于跳转指令还会计算它的目标地址。

主要是为了给 分支预测检查器 :

  • 提供指令信息
  • 正确的目标地址
  • 以及及时更新预测器中的指令信息

另一方面,预译码器也会将压缩指令(如果这个指令块里有的话)扩展为 32 bits 的长指令以便于后续简化译码逻辑。

分支预测检查

分支预测检查器在拿到指令的预译码信息之后主要针对以下几个错误检查:

  • jump 指令预测不跳转的错误:针对 jal 和 ret 这两种种必定跳转的指令检查,如果这个块的 有效指令范围 内有这两种指令,且预测为不跳转,则视为预测错误。
  • 非跳转指令的预测错误:如果预测为跳转的指令不在有效指令范围内,或者在有效指令范围内但是不是一条跳转指令,则视为预测错误。
  • 目标地址错误:对于可以通过指令码知道目标地址的跳转指令(除了 jalr 之外的跳转指令),如果在有效指令范围内且预测跳转并且跳转目标地址和正确地址不匹配,则视为预测错误。

在发现错误后,分支预测检查器挑选出指令顺序最靠前的预测错误指令,把错误信息(错误指令在块里的位置、指令预译码信息、正确的目标地址)传递给 FTQ ,同时清空 IFU 流水线。IFU 等待 FTQ 重新发取指令请求。

跨行指令处理(Cross-line Fetch)

        由于我们的指令块包括了 32 bytes 的指令码,相当于半个 cache line(64 Bytes)的大小,如果这个块的起始地址在后半个 cache line 里,那么完全有可能发生块的范围跨过两个 cache line 的情况;

        因此在指令缓存支持一次取两个 cache line 以保证这种情况下的指令吞吐。具体做法是当 FTQ 发现块的起始地址在后半个 cache line 里,就发起对指令缓存两个相邻 cache line 的请求。

有效指令范围

一个取指令块的有效范围由 FTQ 给出的起始地址跳转指令的 index(如果有跳转的话)共同确定,如果这个块没有跳转指令,则默认指令有效范围为起始地址开始的 256 bits

有效指令范围可能被 IFU 的检查重新确定,主要包括:

  • 分支预测检查发现有未预测跳转的 jal 和 ret 指令时,需要重新将有效指令范围缩短到第一条这样的跳转指令;
  • 前一个块有半条 RVI 的情况,紧随其后的这个块的第一个 16 bits 不在有效指令范围内。
  • MMIO 请求的块的指令有效范围只有 32 bits;

MMIO 取指令

在 IF3 阶段,如果 ITLB 发现这个地址是 MMIO 空间的,IFU 就启动 MMIO 取指令模式:

  • 向指令 MMIO 模块发送请求,指令 MMIO 模块向 MMIO 总线发送 Get 请求 64 bits 的数据
  • 等待总线返回后根据 IFU 的请求地址对数据进行裁剪,返回指令码。
  • IFU 将指令码进行扩展之后发送给指令缓冲队列。
  • 同时,IFU 阻塞流水线,侦听 ROB 的 commit 信号,直到指令执行完后发送前端重定向取下一条指令。

MMIO 请求每次只取一条指令,因此在这种模式下处理器的指令执行速度会变得非常慢。

半条 RVI 指令的处理

当一个指令块在 IF3 阶段发现它的最后 2 bytes 是一条 RVI 指令的前半部分时,我们把这条 RVI 指令算在这个块里,同时我们取两个 cache line 的机制保证后半部分是一定可以被取到的,因此我们只需要在发生这种情况的时候置一个标识位,当下一个块来的时候把第一个 2 bytes 排除在指令的有效范围之外即可。

指令缓存(Instruction Cache)

缓存部分不做过多描述;

译码单元 (Decode Unit)

基本功能

指令从指令缓存中取出,送进指令缓冲(队列)中暂存,然后以每周期 6 条的的速度送入译码单元译码,再传给下一个流水级。

指令融合 (Instruction Fusion)

译码单元支持了一些指令的融合,在 FusionDecoder 模块中会基于连续两条指令的 32bit 数据完成指令融合。对非连续的两条指令,目前香山没有支持指令融合。

目前,香山支持如下情况的指令融合:

  • clear upper 32 bits / get lower 32 bits: slli r1, r0, 32 + srli r1, r1, 32
  • clear upper 48 bits / get lower 16 bits: slli r1, r0, 48 + srli r1, r1, 48
  • clear upper 48 bits / get lower 16 bits: slliw r1, r0, 16 + srliw r1, r1, 16
  • sign-extend a 16-bit number: slliw r1, r0, 16 + sraiw r1, r1, 16
  • shift left by one and add: slli r1, r0, 1 + add r1, r1, r2
  • shift left by two and add: slli r1, r0, 2 + add r1, r1, r2
  • shift left by three and add: slli r1, r0, 3 + add r1, r1, r2
  • shift zero-extended word left by one: slli r1, r0, 32 + srli r1, r0, 31
  • shift zero-extended word left by two: slli r1, r0, 32 + srli r1, r0, 30
  • shift zero-extended word left by three: slli r1, r0, 32 + srli r1, r0, 29
  • get the second byte: srli r1, r0, 8 + andi r1, r1, 255
  • shift left by four and add: slli r1, r0, 4 + add r1, r1, r2
  • shift right by 29 and add: srli r1, r0, 29 + add r1, r1, r2
  • shift right by 30 and add: srli r1, r0, 30 + add r1, r1, r2
  • shift right by 31 and add: srli r1, r0, 31 + add r1, r1, r2
  • shift right by 32 and add: srli r1, r0, 32 + add r1, r1, r2
  • add one if odd, otherwise unchanged: andi r1, r0, 1 + add r1, r1, r2
  • add one if odd (in word format), otherwise unchanged: andi r1, r0, 1 + addw r1, r1, r2
  • addw and extract its lower 8 bits (fused into addwbyte)
  • addw and extract its lower 1 bit (fused into addwbit)
  • addw and zext.h (fused into addwzexth)
  • addw and sext.h (fused into addwsexth)
  • logic operation and extract its LSB
  • logic operation and extract its lower 16 bits
  • OR(Cat(src1(63, 8), 0.U(8.W)), src2)
  • mul 7-bit data with 32-bit data

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

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

相关文章

抓住最后机会!24年PMP认证报名今日开始,流程详解助你成功

为减少同一时间集中报名造成的网络拥堵,本次报名将采取以下形式分地区、分批次开放报名。 一、考试安排 考试时间:2024年11月30日 第一批报名城市 2024年10月9日10:00至10月16日16:00,以下城市的考点将开通报名&…

城市交通场景分割系统源码&数据集分享

城市交通场景分割系统源码&数据集分享 [yolov8-seg-C2f-Faster&yolov8-seg-GhostHGNetV2等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Glob…

FineReport打开报错“配置数据库出错“怎么解决?

配置数据库被锁住,是否重置?将在embed文件夹生成备份并重置 我直接用管理员身份证打开就完美解决了!

fmql之Linux下AXI GPIO、MISC

AXI GPIO 正点原子第41章。 要使用AXI GPIO,就要在vivado工程中,添加相关的IP。 然后dts会自动生成相关的AXi GPIO的设备树内容。 MISC 正点原子第42章。 /***************************************************************Copyright © ALIENTE…

C++--特殊类的设计

下面所实现类的源码:源码链接 不可拷贝类 在C中,我们有时候需要设计一些不可拷贝的类,即不允许用户通过拷贝构造函数或赋值操作来创建该类的副本。这样设计通常是为了确保资源(如文件描述符、窗口句柄等)的唯一性&…

(JAVA)熟悉队列的进阶结构 - 优先队列

1. 优先队列 ​ 普通队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。 ​ 在某些情况下,我们可能需要找出队列中的最大值或者最小值,例如使用一个队列保存计算机的任务,一般情况下计算机的任务都是有…

FTP连接池与多线程上传下载算法实现(C语言)

FTP连接池与多线程上传下载算法实现(C语言) 设计思路伪代码示例C代码示例为了避免多线程环境下FTP连接池在故障重连时导致的竞争条件和core dump问题,我们需要设计一个精细的连接池管理系统,确保在连接重连时,其他线程不会尝试使用该连接。以下是一个简化的设计思路和示例…

开源计算器应用的全面测试计划:确保功能性和可靠性

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

Navicat图形化设置字段unique

点击索引,选择字段和索引类型即可。

前端学习笔记-JS进阶篇-04

1、深浅拷贝 开发中经常需要复制一个对象。如果直接用赋值会有下面问题: 首先浅拷贝和深拷贝只针对引用类型 1.1、浅拷贝 浅拷贝:拷贝的是地址 常见方法: 1.2.1、 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象…

目标检测指标:AP,mAP

目标检测指标:AP,mAP 论文:A Survey on Performance Metrics for Object-Detection Algorithms 文章目录 目标检测指标:AP,mAP摘要1 介绍2 主要的性能指标TP、FP、FNP、RAP A P 11 AP_{11} AP11​ A P a l l AP_{all}…

金慧-综合管理信息系统 LoginBegin.aspx SQL注入复现

0x01 产品描述: 金慧-综合管理信息系统(以下简称“金慧综合管理系统”)是上海金慧软件有限公司基于多年行业系统研发和实施经验,为各类企业量身定制的一套综合性管理解决方案。该系统旨在通过信息化手段,提升企业的管理…

openstack-swift.18421165

对象存储 swift 对象存储 是一种用于存储和管理大量数据的系统。类似于一个超大云盘。可以存储各种文件。(照片,视频,文档等等)。与传统的文件存储不同,对下个存储不关心文件的目录结构和层级关系,而是将每…

嵌入式仿真实验教学平台

一、基本介绍 嵌入式仿真实验教学平台:嵌入式硬件仿真、线上实验教学、虚实结合场景实训 二、案例 AVG场景实训 智能家居场景实训 智慧农业场景实训 智慧物流场景实训

Python【修炼2】

欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:Python 目录 👉🏻map👉🏻lambda👉🏻datetime日期输出格式 👉&#x1f3fb…

Airtest脚本的重构与优化:提升测试效率和可读性

在自动化测试的工作里,编写高效且易于维护的测试脚本是一项挑战,尤其是在应对复杂的测试场景时。Airtest作为一款常用的自动化测试工具,它提供了丰富的API和灵活的脚本编写方式,帮助测试人员高效地开展UI自动化测试。然而&#xf…

头戴式耳机性价比高的有哪些?五大高性价比头戴式耳机推荐!

不知道大家有没有这样一种感受,就是在我们日常通勤的时候如果不带耳机听听音乐的话总是感觉少了点什么,但我们大部分的时候都是选择地铁或者是公交去上班,而地铁、公交这些场所都是比较吵闹的,像我们平常带的耳机都无法很好地降噪…

架设传奇SF时提示此服务器满员,GEE引擎点开始游戏弹出服务器满员的解决方法

昨天一个朋友在架设GEE的传奇服务端时遇到一个奇怪的问题,就是在服务器外网架设时,建好角色点开始游戏提示此服务器满员,这个问题一般比较少见,而且出现的话一般都是GEE引擎的版本。 他折腾了半天,一直没进游戏&#x…

shiny APP实现xgboost 构建,超参数调节以及后概率校准

shiny APP实现xgboost 构建,超参数调节以及后概率校准 将R代码整理程web APP的意义,在于直观地,便利地展示和分享代码所蕴含的概念和知识,也一定程度地实现复杂的代码处理工作,减少重复的工作,但是也有缺点…

HashMap如何put一个数值

1.根据key计算一个hash值。 2.在put的时候判断数组是否存在,如果不存在调用resize方法创建默认容量为16的数组。 3.确定node在数组中的位置,根据hash值和数组的最大索引值进行与运算得到索引的位置。 4.获取该位置是否有元素,如果没有元素…