超标量处理器设计——第九章_执行

news2025/1/20 18:28:44

参考《超标量处理器》姚永斌著

文章目录

  • 超标量处理器设计——第九章_执行
    • 9.1 概述
    • 9.2 FU类型
      • 9.2.1 ALU
      • 9.2.2 AGU
      • 9.2.3 BRU
        • 条件码
        • 分支正确性检查
    • 9.3 旁路网络
      • 9.3.1 简单设计的旁路网络
      • 9.3.2 复杂设计的旁路网络
    • 9.4 操作数的选择
    • 9.5 Cluster
      • 9.5.1 Cluster IQ
      • 9.5.2 Cluster Bypass
    • 9.6 存储器指令的加速
      • 9.6.2 非阻塞Cache
      • 9.6.3 关键字优先
      • 9.6.4 提前开始
      • 9.6.5 I-Cache的处理

超标量处理器设计——第九章_执行

9.1 概述

  • 每个FU都有一个1-M仲裁器, 每个仲裁器和物理寄存器堆的读端口一一对应

9.2 FU类型

9.2.1 ALU

  • Arithmetic and Logic Unit

  • MIPS中如果加减法发生溢出, 需要产生异常

  • ARM中, 直接定义了状态寄存器CPSR:

    • ARM中定义了四种加减法操作:

      1. 不带进位加: X + Y = X+Y+0
      2. 带进位加: X + Y + Cin
      3. 不带借位减: X-Y = X + (~Y + 1) , 实际就是补码运算
      4. 带借位减: X-Y-1 = X + (~Y+1)-1 = X + (~Y)
  • 一些ALU可能还会包含简单的乘除法, 而这些操作周期数较多,对bypass功能引入了一些复杂度:

  • MIPS和ARM都集成了CLZ (Counting Leading Zero),用来判断32位寄存器从高位开始连续0的个数, 用来做优先级判断:

  • 一些处理器使用单独的乘法器FU获得高并行度, 还会自带乘累加功能(MADD)

  • 一些处理器为了节省面积,将整数转换成浮点数,放入浮点FU中计算乘法

9.2.2 AGU

  • Address Generate Unit
  • Load/Store携带的存储器地址通过AGU处理
  • 普通流水线处理器中一般这个工作交给ALU处理, 但是超标量处理器为了并行执行,单独使用一个FU来计算地址

9.2.3 BRU

  • Branch Unit
  • 负责分支指令: branch, jump, Call, Return等
  • 将指令携带的目标地址计算出来,根据条件决定是否使用
  • 还存在分支预测正确性检查

条件码

  • ARM和PowerPC采用与MIPS不同的分支方法, 即条件码:

  • 条件码的优点:

    • 条件码降低分支指令使用频率, 对超标量处理器来说能获得更好的性能.
  • 缺点:

    • 条件码占据了指令编码的一部分,导致可分配给寄存器的部分变少了,例如ARM加入了4位条件码后, 实际可用的指令编码空间就只有32-4=28位了. 简介导致其只支持16个通用寄存器.

    • 此外,条件码会使得所有指令都进入流水线, 会存在大量无效指令, 效率不高

    • 另外, 条件码的可能导致寄存器重命名时的额外麻烦:

    • 该图中,如果SUBNE不执行, 那么ADD就会使用错误的物理寄存器P7, 而实际上应该用的是P6

    • x86对该问题的一个解决方案是硬件插入额外的指令:

    • uOP指令根据两个条件执行的结果对物理寄存器进行选择, 但是必须保证条件执行指令成对出现

分支正确性检查

  • 在流水线的取指阶段会将预测跳转的分支指令保存在一个缓存中, 称为分支缓存(branch stack)
  • BRU的到一条分支的结果时, 会在分支缓存中进行查找, 有四种情况:
    1. BRU的结果是跳转, 且分支缓存中能找到他, 跳转地址也相同 ---- 预测正确
    2. BRU的结果是跳转, 但是分支缓存中找不到他 ---- 预测失败
    3. BRU的结果是不跳转, 且分支缓存中找不到他 ---- 预测正确
    4. BRU的结果是不跳转, 但是分支缓存中能找到他 ---- 预测失败
  • 如果预测正确, 释放该分支占用的资源, 如checkpoint或分支缓存

9.3 旁路网络

  • 目的: 为了使存在相关性的指令能背靠背执行

  • 源操作数从物理寄存器读出,还需要经过一段时间才能到FU输入口, 这些周期称为Source Drive阶段

  • FU将一条指令结果计算出来后, 还需要经过复杂的旁路网络才能到达所以FU的输入(或PRF输入), 这个阶段称为Result Drive阶段.

9.3.1 简单设计的旁路网络

  • 当一个FU中有多个功能, 例如ALU可以计算移位,也可以计算加减法. 对这样的FU需要用多路选择器, 从不同的计算电路中选择一个结果放到旁路网络, 这种做法称为 bypass sharing

  • 如果一个FU中所有计算单元周期数不等, 可能会导致某一个周期FU中的两个计算单元竞争旁路网络的情况:

  • 一种解决方法是借鉴推测唤醒的做法, 一条指令在到达FU之前,先检查FU是否可以被自己使用. 例如上个周期FU执行了latency = 3的指令, 那么本周期就不能执行latency=2的指令了.

  • 具体实现:

    • 用一个两bit的控制寄存器, 每周期会逻辑右移一位.

    • 当本周期被仲裁电路选中的是latency=3的指令, 就在下一周期将控制寄存器设置为2’b10. 表示下周期不允许latency=2的指令参与仲裁. 下下周期控制寄存器变为2’b01, 表示下下周期不允许latency =1的指令参与仲裁

    • 假设本周期仲裁电路选中latency=3的指令, 下周期仍然选中latency=3的指令, 此时的处理是将两次的控制寄存器相或:

9.3.2 复杂设计的旁路网络

  • 指令B可以在Execute阶段从A的Result drive阶段获得操作数

  • 指令C可以在Source drive阶段从A的Result drive阶段获得操作数, 或者C也可以在Execute阶段, 从A的Write Back阶段获得操作数

  • 指令D可以在Source drive 阶段从A的write back阶段或的操作数

  • 指令E在流水线RF read阶段读取物理寄存器堆(PRF)时, 可以的到指令A的结果, 所以其不需要从旁路网络获得操作数

  • 旁路网络会使得流水线变得很复杂:

    • 可以发现, 在上述流水线中, 当两条指令间隔的指令超过两条时, 就不需要通过旁路网络或的操作数了

    • 增大流水线级数会导致更复杂的旁路网络

    • 不需要在所有FU之间都设置旁路网络, 例如AGU会用到ALU结果, 但是ALU不会用到AGU的结果

9.4 操作数的选择

  • FU 的输入端需要从物理寄存器的输出或所有旁路网络中进行选择.

  • 一个物理寄存器在生命周期内会有多种状态, 他可能被写到PRF, 还可能需要在指令顺利离开流水线时写到ARF中. 这些信息都可以保存在一个表格内,称为 ScoreBoard

  • FU# : 从旁路网络取出某个物理寄存器时,需要知道来自哪个FU, Scoreboard的FU#记录了该信息. 当一条指令被仲裁器选中时, 如果指令有目的寄存器, 那么就将该指令在哪个FU中执行的信息写到该表中

  • R : 表示该寄存器已经被FU计算完毕, 并写到了PRF中, 后续指令如果要使用该寄存器器, 可以直接从PRF中读取. 如果该位为1, 就不需要关注FU#信息了.

  • 在流水线中加入该表格:

    • 会影响Select阶段(写入FU#)和Write Back阶段(更新R)

    • 上图中指令C可以在EX阶段读取Scoreboard, 因为A已经将结果写到PRF了, 所以此时C读取SB后知道应该去PRF中取操作数, 但是这样会导致EX阶段延时变长. 对应的电路如下:

    • C指令其实在RF read阶段就开始读取SB, 打一拍后进入EX:

      • 这种方法能缓解EX延时过长的问题, 但是会导致C读SB时, R位还没有置1, C会错误的认为自己应该从旁路网络去获得操作数

      • 可以简单地打个补丁, 也就是如果发现写入SB时(更新R)与读取SB时(RF阶段读取FU#)所用的物理寄存器相同(一个地址), 就将EX的多路选择器切到PRF上, 而不是实际读出的FU#

  • 如果处理器每周期可以执行N条指令, 那就需要SB有2N个读端口, 而SB需要分两次写如FU#和R, 所以又需要2N个写端口!

  • 除了使用SB, 另一个方案是使用比较器产生MUX的控制信号:

    • FU在将计算结果广播到bus上时, 同时也将该指令的目的寄存器编号也一起广播
    • 每条指令在从旁路网络选择操作数的两个周期内, 也就是Source Drive和Ex阶段将源操作寄存器编号和FU送来的目的寄存器编号进行比较, 如果相等, 说明此时需要从旁路网络获得操作数, 否则就是从PRF获取.
    • 代价是更大的面积和功耗, 但是很简单.

9.5 Cluster

  • Cluster是一种结构实现的思路, 例如将浮点FU和整数FU的旁路网络分开, 或者将一个IQ分为多个独立的IQ

9.5.1 Cluster IQ

  • 集中式的IQ往往需要更多的读写端口和更大的容量, 导致面积和延时都很大

  • 可以使用Cluster的结构, 将集中IQ拆分成多个小的分布式IQ, 每个IQ只对应一个或几个仲裁电路和FU

  • 带来的优点:

    1. 可以减少每个分布式IQ的端口个数
    2. 每个分布式IQ的仲裁电路只需要负责很小一部分的指令, 可以加快仲裁电路的速度
    3. 分布式IQ的容量较小, 其中的指令被唤醒的速度也较快
  • 缺点:

    1. 被仲裁电路选中的指令对其他IQ中的指令进行唤醒时, 走线会更长, 延迟会增大, 甚至需要增加一级流水, 此时原来有相关性的两条指令就不能背靠背了, 会引入一个bubble.
  • 解决办法

    • 例如:下图中的五条指令,只需要一个周期就可以从FU中得到结果,相关性如图:
    • 正常情况下: 第一个周期A,B被仲裁选中, 第二周期CD选中,第三周期E选中

    • 采用了分布式的IQ之后,假设跨越Cluster唤醒需要消耗一个周期,此时有两种情况:

      1. ABE在一个cluster,指令CD在另一个Cluster中。AB在被选中后,要等一个周期才能唤醒C和D, D被选中后也要等一个周期才能唤醒E:

      2. AC分到同一个Cluster中, BDE分到另一个Cluster中:

      • 可见执行效率跟在不在一个Cluster有关,需要仔细规划分配算法
  • 对于非数据捕捉结构的超标量处理器, 指令在被仲裁电路选中后会先读取PRF, 因此需要PRF支持多个读端口,可以对寄存器堆也使用Cluster结构:

    • 这种做法可以减少读端口,但是无法减少写端口

    • SRAM的面积近似跟端口个数的平方成正比,因为布线资源随端口数平方增长,所以减少读端口仍然可以减少面积。

9.5.2 Cluster Bypass

  • 对旁路网络使用Cluster之后, 旁路网络只分布在每个Cluster内部:

  • 因为旁路网络大幅度简化了,所以可以去掉Source Drive和Result Drive两个阶段,节省了两级流水,这一同一个Cluster的指令仍然可以背靠背,不同Cluster的指令只需要间隔1个周期:

  • 将一个FU的结果送到其他Cluster的FU输入往往延时较大, 所以可能需要为此加一级流水:

  • 跨Cluster进行唤醒会引入一个周期延迟, 跨FU的旁路网络也需要一个周期延时,但是实际上这两级延时不是叠加的,而是合并的:

9.6 存储器指令的加速

9.6.1 Memory Disambiguation

  • LOAD, STORE指令之间也有相关性:

  • 一般store指令都是顺序执行的,这样可以避免WAW相关性,但load可以有不同的实现方式:

    1. 完全的顺序执行

      • 最保守,不能将load提前执行,导致所有相关指令执行都偏晚
    2. 部分的乱序执行

      • 每当一条store指令的地址被计算出来后,这条store和它后面的store指令之间的所有load都可以乱序

      • 两条stroe指令之间的load可以乱序, 避免了WAR相关性

      • 当一条store被仲裁电路选中,位于其后的load就可以参与仲裁了,且这些load可以乱序地被选中

      • 但是被选中的load还是需要和前面所有已经执行的store指令携带的地址进行比较,以判断RAW相关性

      • 需要一个缓存来保存被仲裁电路选中但还没顺利离开流水线的store指令,该缓存称为Store Buffer

      • 如果load在store buffer中发现了地址相等的store指令, 说明发现了RAW相关性,直接从该缓存中就可以得到load所需的数据

      • store就像一扇门, 当其被仲裁电路选中之后,就可以开门,放行之后的load指令进入仲裁器:

      • 实际上,这种方式只保证store指令是顺序的,例如A先执行,A唤醒了C,但是B,D还没进入仲裁;此时指令E又被仲裁电路选中,它使得F和G也有资格参与仲裁;因此这时B,D,F,G都可以被仲裁电路乱序选中

      • 新的问题:E指令先于B,D被仲裁选中时,指令B和D被选中时查找Store buffer会有两条store指令,但是B,D与E实际没有相关性,因此需要鉴别Store Buffer中哪些store在本条load的前面,哪些在后面。有如下方法:

        1. 用PC值标记先后顺序。实际不可靠,因为如果store之后有向前跳转的指令,该方法就失效了:

        2. 用ROB编号。ROB记录了指令进入流水线的先后顺序,ROB中的地址可以表示先后。但是实际ROB不止存放load和store,导致这个标号非常稀疏,比较大小时浪费比较器面积

        3. 在解码阶段,为load和store分配一个编号,编号宽度根据流水线最多支持的load/store来决定

      • 这些记录load,store顺序的标号固然可以解决问题,但是带来了复杂度,实际上可以要求B,C,D都被仲裁电路选中之后,才能让E进入仲裁。当然代价是牺牲性能,因为如果store指令A发生缺失,E就不能被选中:

      1. 完全的乱序执行
        • store仍然是顺序执行,但load将不再受限于它前面的store指令,只要其操作数准备好,可以立即参与仲裁
        • load的仲裁,可以按照oldest-first的策略,乱序进入仲裁器(这里的乱序指的是不需要关store在前还是在后)
        • 可以这么做是基于一个观察:RISC处理器中,ARF的数量实际是较多的,很多变量可以直接放到寄存器中。程序中store/load指令间的RAW相关性不会很多,可以通过提前执行load来尽快唤醒更多指令,以获得更大的并行性
        • CISC处理器中由于可用的通用寄存器较少,需要经常跟mem进行通信。Store/load存在RAW的情况就较多:
          • Store/Load指令违例: 如上图, 本来在Store下方的Load提前到store之前执行, 如果r5=r9, 将导致违例

          • Load/Store相关性预测: 预测load指令和前面的store指令存在RAW相关性而不能被提前执行

          • 硬件处理store/load违例不多见, 通常在比较新的指令集会考虑,例如VLIW处理器领域的intel Itanium:

            • 对一条提前到store指令之前的load指令进行标记:

            • load.a就是做了标记的指令, 该指令除了load数据外, 还会将load计算出来的地址放到一个表格ALAT(Advanced Load Address Table)中:

            • Size表示存储word, halfword 或byte

            • 没当store指令计算出来地址,都会据此来查找ALAT, 因此需要Address表项支持内容寻址功能(CAM)

            • 如果发现携带地址想他的load指令,会将该load踢出ALAT, 让store指令占据这个位置, 表示发现了load指令违例

            • load指令被提前调度到store之前时, 会在调度后的load加上.a标记, 同时也会在load原来所在的位置加上一条新的指令 load.c

            • load.c指令会检查ALAT,如果发现自己不在ALAT中(被store踢出), 表示发生了违例, 需要进行修复. 修复通常是一段fixup code固定代码

            • 顺带提一句,虽然intel Itanium开发了新的指令集,但是失败了…

9.6.2 非阻塞Cache

  • 在RISC中, 只有像load和store这样的访存指令才可以访问mem
  • 对于load指令, 如果发生D-Cache缺失,需要找到一个Cache line放入内存中的数据, 如果Cache line是脏的,还要把line的数据块先写回物理内存
  • 对Store指令来说, 如果他的地址不在D-Cache中,那么对于write back+ write allocate类型的Cache来说, 要先从内存中找到地址对应的数据块, 将其取出, 和store的数据进行合并, 再从D-Cache中按照某种算法找到一个Cache line放入.如果被替换的line是脏的, 那在写入之前还要把这个数据协会内存
  • 如果在某个访存指令处理D-Cache miss期间, 又有新的访存指令发生了miss, 该如何?
    • 一种方法是miss之后, 阻塞其他load store指令, 这种就是阻塞(Blocking)Cache:

    • 性能很低, 因为一般load在数据相关性的顶端

    • 非阻塞(Non-blocking)Cache: 也叫lookup-free Cache, 允许D-Cache miss 的时候继续执行新的访存指令:

    • 需要在scoreboard中将发生D-Cache缺失的load指令的目的寄存器标记为不可获得的状态.

    • 带来的问题: load.store指令的Cache miss处理完的时间可能和原始指令顺序不一样. 例如load1需要从内存中导入数据, load2只需要从L2 Cache中导入

    • 处理器需要将产生D-Cache miss 的load/store指令保存到一个部件中, 该部件就是MSHR(Miss Status/information Holding Register), 也叫做 MAF(Miss Address File):

      • 先了解几个概念:

        1. 首次缺失(Primary Miss): 访问D-Cache时第一次产生的缺失
        2. 再次缺失(Secondary Miss): 发生首次缺失且没有被解决完之前, 后续的访存指令再次访问这个发生缺失的Cache line
      • MSHR中:

        1. V: Valid位, 表示表项是否被占用, 首次缺失发生时, 会占用一个表项, 当Cache line从下级存储器被取回时, 会释放表项, valid清除
        2. Block Address: Cache line中数据块的公共地址. 假设Cache line数据块大小是64byte, 则需要6位来索引. 对于一个32位的物理地址, 其余的26位就是数据块的公共地址. 每次load/store发生缺失时都会在MSHR查找所需数据块是否正在被取回
        3. Issued: 发生首次缺失的访存指令是否开始处理. 因为存储器带宽有限, 所以占用MSHR本体的首次缺失不一定马上被处理, 而是得等到条件满足时才会向下一级存储发出读数据请求.
      • LOAD/STORE Table: 记录首次缺失和再次缺失的访存指令

        1. V: valid位, 表示是否被占用
        2. MSHR entry: 表示一条发生缺失的访存指令属于MSHR本体中的哪个表项. 由于产生miss的很多访存指令可能对应同一个Cache line, 他们只占用一个MSHR表项, 但是需要占用LOAD/STORE TABLE中的不同表项. 如此, 当缺失数据块从下级存储取回时, 可以根据block address定位到MSHR中的位置, 并据此在LOAD/STORE TABLE中找到哪些指令属于该cache line
        3. Dest.register:
          • 对load指令来说, 这部分记录目的寄存器(物理)编号, 当数据块取回时, 就可以将对应数据送到这部分记录的寄存器中.
          • 对store指令来说, 这部分记录store指令在store buffer 中的编号. 当store指令发生缺失, 它的数据不会立即写到cache ,而是停留在store buffer. 当下级存储器取回数据后, 才将要存储的数据合并到数据块, 再将合并后的数据写到D-Cache, 此时才能从Store Buffer中释放该store占据的空间. 所以LOAD/STORE TABLE中的这个表项一是为了找到store指令携带的数据, 二是释放store占据的store buffer空间.
        4. Type: 记录访存指令的类型., 例如Load Word, Load Half word等
        5. Offset: 访存指令所需数据在数据块中的Byte偏移
    • MSHR和LOAD/STORE TABLE的配合可以支持非阻塞Cache的操作方式:

      1. 当访存指令发生Miss时, 查找MSHR, 将发生Miss的地址与MSHR的所有block address进行比较.
      2. 如果发现想等的表项存在, 表示缺失数据块正在被处理,这次是再次缺失, 此时只需要将这条访存指令写到LOAD/STORE TABLE即可
      3. 如果没有发现想等表项, 表示此时是首次缺失, 需要将该指令写到MSHR和LOAD/STORE TABLE
    • 如果MSHR或LOAD/STORE TABLE任意一个满了, 表示不能在处理新的访存指令, 应该让流水线暂停选择新的访存指令

    • MSHR容量不会很大, 多为4-8个 ^737697

    • 非阻塞Cache虽然性能较高,但是会占用较大的面积:

      • 以8个表项MSHR和16个表项的LOAD/STORE Table为例:
    • 为了解决MSHR占用面积大的问题, in-Cache MSHR的方法被提出:

      • D-Cache miss时, 从下一级存储器中提取数据, 此时D-Cache中的这一个cache line是空闲的, 没起任何作用.
      • 可以将这个cache line作为存储MSHR的地方, 不过需要在cache line中再加一位, 称为transient bit, 表示这个Cache line中的数据正在从下一级存储器中被取回
      • 当Cache line处于该模式, 其tag用来存储block address, 其他部分保持MSHR信息
    • in-cache的缺点是:

      1. Cache的读端口宽度一般远小于Cache line中数据块大小. 例如每周期可以执行4条指令的处理器, D-Cache的读端口一般小于4个, 每个读端口宽度都是32位, 则读带宽最多就4*4=16byte, 远小于Cache line中数据块大小, 导致需要多个周期才能从Cache line中将MSHR的信息读出来
  • 超标量处理器中, 非阻塞Cache实现会更复杂一些, 由于采用分支预测和乱序执行, 一些引发Cache miss的load/store指令可能处于预测失败的路径上, 因此需要一种机制来选择性地放弃一些正在处理的D-Cache miss:
    1. 如果一条load在分支预测失败的路径上, 则该指令需要从流水线中抹除, 且还需将LOAD/STORE Table中相应表项删除
    2. 如果某个发生缺失的数据块正在从下一级取回, 此时发现访问该数据块的所有load/store都处在分支预测失败的路径上, 那么这个数据块不应该被写入D-Cache

9.6.3 关键字优先

  • 当发生D-Cache缺失时, 要将该指令所要的整数个数据块从下级存储取出, 如果考虑预取(prefetching), 还要将相邻的下个数据块也取出:

  • 如果等到所有数据都写到D-Cache之后才将所需要的数据送给CPU, 这会让CPU等待一段时间. 可以对D-Cache进行改造来加快执行速度:

  • 关键字优先(Critical Word First): 如果访存指令需要的数据位于数据块中的第6个字, 则此时可使下一级存储器的读取从第6个字开始, 读到数据块结束后,再回过来读前面0-5个字. 这样CPU可以在第6个字读出后就继续执行. 代价是下级存储器需要为支持这样的特性增加硬件逻辑.

9.6.4 提前开始

  • 关键字优先需要在下级存储中增加额外的硬件支持, 如果不想付出这些成本, 可以采用 提前开始(Early Restart) 的方法:

  • 提前开始的思路是: 第六个字读出后, CPU开始继续执行

  • 与关键字优先的区别是, 这种方法不会改变数据读取的顺序

9.6.5 I-Cache的处理

  • 目前位置的非阻塞Cache, 关键字优先, 提前开始三种方法, 都可以应用到D-Cache, 也可以应用到I-Cache

  • 由于超标量处理器一般都有分支预测, 会根据当前指令地址对下一条指令的地址进行预测. 如果某次读取I-Cache时发生缺失, 并且预测器预测这条指令正好是分支跳转指令, 则大概率会引发两次miss, 因为预测跳转的分支所用的指令大概率不在I-Cache中:

  • 因此I-Cache也可使用非阻塞结构:

  • I-Cache不需要使用太大的MSHR容量, 有时用1个MSHR表项就够了(MIPS R10000)

  • I-Cache使用这些方法与D-Cache的区别是, I-Cache需要保证指令的原始顺序, 即使后面的指令先被取出, 也要等待前面的指令取出

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

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

相关文章

Python 自动化测试(四):数据驱动

在实际的测试工作中,通常需要对多组不同的输入数据,进行同样的测试操作步骤,以验证我们的软件质量。这种测试,在功能测试中非常耗费人力物力,但是在自动化中,却比较好实现,只要实现了测试操作步…

前端基础_fillStyle和strokeStyle属性

fillStyle和strokeStyle属性 在前面的章节,在绘制图形时只用到默认的线条和填充样式。而在本节中将会探讨canvas全部的可选项,来绘制出更加吸引人的内容。如果想要给图形上色,有两个重要的属性可以做到:fillStyle和strokeStyle。…

社科院与杜兰大学金融管理硕士12门课程简介,其中有你心心念念的课程吗

当我们考量一个项目是否符合自身时,首先对课程设置是有要求的,课程设置是一个项目的灵魂所在,优质的课程与强大的师资更能体现项目的与众不同,下面一起去了解社科院与杜兰大学金融管理硕士项目12门必修课程概要,看看其…

【Java】java | maven | nexus私服 | maven私服 | docker安装nexus私服

一、说明 1、centos 7 2、docker 3、idea的maven项目 二、安装 1、拉取镜像 docker pull sonatype/nexus3:latest 2、创建映射目录并授权 mkdir /home/nexus/nexus-data && chown -R 200 /home/nexus/nexus-data 3、启动镜像 docker run -d -p 8081:8081 -p 8082:8082…

antd+vue——实现按钮始终固定在顶部,且根据权限的不同控制按钮组件的显示与隐藏——技能提升

最近在写后台管理系统,遇到一个小功能,就是一个按钮组件集合。 之前写过一篇文章,是关于按钮集合固定到页面顶部的文章。vue——实现页面滚动时,dom固定在顶部——基础积累 原理就是:监听页面的滚动,如果…

QT Qmake OpenGL osg笔记

文章目录概述QT修改样式qmake概述库引用和库路径指定QT创建动态库和使用小例子写动态库用动态库参考资料附录概述 需要先安装osg,然后再编译安装osgQOpenGL的插件。 其中,osgQOpenGL是OSG嵌入到qt中的一种实现方式,换言之,能够支…

AMBA、AHB、APB、AXI总线介绍及对比

link 一、AMBA概述AMBA (Advanced Microcontroller Bus Architecture) 高级微处理器总线架构定义了高性能嵌入式微控制器的通信标准,可以将RISC处理器(精简指令集处理器)集成在其他IP芯核和外设中,它是有效连接IP核的“数字胶”&a…

或许是市面上最强的 Mock 工具

背景 在开发过程中,由于后端与前端并行开发,或者前端需要等待后台开发,难以保证对接效率,同时即使用开发好的 API 对接,也有可能一个 API 不通就阻塞了整个软件的对接工作。同时对软件的敏感度也很高,一不…

冯·诺依曼:计算机硬件与软件Computer

计算机硬件与软件 计算机(Computer):俗称电脑,是一种能接收和存储信息,并按照存储在其内部的程序对海量数据进行自动、高速地处理,然后把处理结果输出的现代化智能电子设备 冯诺依曼体系结构: …

cubeIDE开发, STM32移植GuiLite图形库开发要点

一、GuiLite GuiLite图形库,仅4千行C代码,0依赖,单一头文件库(GuiLite.h)的跨平台开源GUI库,支持支持的操作系统有iOS/macOS/WatchOS,Android,Linux(ARM/x86-64&a…

Filter过滤器 | 过滤器的使用以及实现原理、责任链设计模式改造oa项目

目录 一:过滤器的使用以及实现原理 (1)当前的oa项目还存在什么缺陷? (2)Filter是什么,有什么用,执行原理是什么? (3)过滤器怎么写&#xff1f…

蓝桥杯:作物杂交 (DFS)

目录 题目描述 输入描述 输出描述 输入输出样例 输入 输出 样例说明 思路(DFS): AC代码(Java): 题目链接 题目描述 作物杂交是作物栽培中重要的一步。已知有 N种作物 (编号 1 至 N ),第…

[第十二届蓝桥杯/java/算法]B——空间

🧑‍🎓个人介绍:大二软件生,现学JAVA、Linux、MySQL、算法 💻博客主页:渡过晚枫渡过晚枫 👓系列专栏:[编程神域 C语言],[java/初学者],[蓝桥杯] &#x1f4d6…

python爬虫技术如何挣钱?教你爬虫月入三万!

前言 爬虫技术挣钱方法1:接外包爬虫项目 这是网络爬虫最通常的的挣钱方式,通过外包网站,熟人关系接一个个中小规模的爬虫项目,一般向甲方提供数据抓取,数据结构化,数据清洗等服务。 各位新入行的猿人看官大多都会先尝…

SpringBoot中的Aop用法

目录什么是AopAop概述相关注解相关概念实例1PointCut 表达式详解executionwithinthistargetargs:annotation:args:逻辑运算符实例2环绕通知什么是Aop 主要介绍springboot中aop的使用,用过Spring框架的都知道,aop是spring框架的两大核心功能之一&#xf…

「实操」适配 NebulaGraph 新版本与压测实践

本文来自邦盛科技-知识图谱团队-繁凡,本文以 NebulaGraph v3.1.0 为例。 前言 NebulaGraph v3.1 版本已经发布有一段时间了,但是我们的项目之前是基于 v2.6.1 版本开发的,由于一直在做功能相关的工作,所以一直没有对图库进行升级…

一个简单的步骤让你的 Python 代码更干净

说起来容易做起来难,我们都知道代码可读性非常重要,但是写的时候总是随心所欲,不考虑类型提示、import 排序、PEP8 规范。今天分享一个小技巧,通过一个简单的步骤就可以让你的 Python 代码更干净。 这就是 pre-commit&#xff1a…

pyQt5和pySide2 环境配置以及部分问题解决方案

首先介绍需要安装的内容: 1、Qt 2、python3.7.5(查找资料过程中有注意到说是3.8及3.8以上版本Qt可能不兼容)【记得勾选添加到环境变量中选项】 3、pip(主要用来下载使用) 4、pySide2、PyQt5、pyqt5-tools 5、如果有使…

vue 前端国际化方案

方案介绍: 1.使用i18n(使用步骤可百度,要注意版本问题) 2.整合ele-ui的国际化方案(百度,几行添加一下即可) 3.数据信息的配置(重头戏,以下详细介绍)excel转j…

中科院高分区盘点:1区新刊,影响因子即将突破7分(含IEEE)

高分新刊——计算机领域 1区人工智能类SCI&EI 【出版社】IEEE 【自引率】4.30%(低) 【国人占比】13.40% 【期刊简介】IF:6.5-7.0,JCR1区,中科院3区 【检索情况】SCI&EI 双检,正刊 【参考周期】3-5个月左…