景区旅游门户网站建设方案wordpress源码商城模板
景区旅游门户网站建设方案,wordpress源码商城模板,网络建设与维护是什么,南京个人做网站VLIWSIMD架构学习
一、VLIW
1、引入 程序执行时间TotalinstructionsCyclesinstructionsSecondsCycles程序总指令数每条指令所需要的周期数每个周期所对应的时间程序执行时间 Total instructions \times \frac{Cycles}{instructions}\times \frac{Seconds}{Cycles} 程序总指…VLIWSIMD架构学习一、VLIW1、引入程序执行时间 T o t a l i n s t r u c t i o n s × C y c l e s i n s t r u c t i o n s × S e c o n d s C y c l e s 程序总指令数 × 每条指令所需要的周期数 × 每个周期所对应的时间 程序执行时间 Total instructions \times \frac{Cycles}{instructions}\times \frac{Seconds}{Cycles} 程序总指令数 \times 每条指令所需要的周期数 \times 每个周期所对应的时间程序执行时间Totalinstructions×instructionsCycles×CyclesSeconds程序总指令数×每条指令所需要的周期数×每个周期所对应的时间根据上面的式子可以看出来有三个因素影响了程序的执行时间。该程序总共需要执行的指令个数由算法决定每条指令所需要的周期数简称CPI微架构决定每个周期所对应的时间工艺决定CPI全称Clock Per Instruction即每个时钟周期能够执行的指令个数它反映了处理器并行处理指令个数的能力。有时候我们也用其倒数形式即IPCInstruction Per Clock。对于非流水线的多周期处理器我们需要多个Cycle才能执行完一条指令对于普通的流水线处理器我们一个周期最多也就执行一条指令IPC最大也就只能为1了还有没有办法让IPC进一步提高呢实际上在程序的指令流中很多指令相互之间是独立的只要处理器有足够的硬件资源理论上它们就可以被同时执行即实现指令级别的并行ILPInstruction Level Parallesim最典型的ILP有以下几种方式流水线有时候提ILP不会提流水线因为处理器设计默认采用流水线超标量Superscalar;超长指令字Very Long/Large Instruction WordVLIW超标量处理器设计是个非常大的话题也是目前高性能CPU的主流技术。本篇文章不讨论超标量处理器而是围绕VLIW展开去思考为何VLIW曾一时风光无限又为何在通用处理器市场败下阵来又是怎么在DSP/NPU等领域重新大放异彩的带着这些问题我们正式进入VLIW的学习。VLIW于1983年由美国计算机科学家Josh Fisher提出并发表于体系结构顶会ISCA上根据VLIW的名字我们就可以知道其指令一定很长。实际也确实如此。VLIW是将多条互相独立的指令通过软件编译器的方式打包Pack在一起我们将打包好的多条指令称为instruction bundle。取指模块根据打包好的指令送入各自独立的功能部件并行执行如下图所示取指模块从指令存储器取出了Instruction Bundle共包含四条指令然后同时发送给后级模块从而实现了指令级并行。此外我们可以看出来其一共有两个浮点部件、三个整数部件、两个存储部件、一个转移部件因此对应的指令Bundle长度为32*8256。根据上面的例子我们不难发现指令一旦送出以后各个功能部件是互相独立的各个指令也是天然并行的。即VLIW不需要通过硬件检查指令与指令之间的依赖关系而是由软件编译器去静态的调度互相独立的指令其优点就是硬件设计将对简单为什么但对于编译器开发工作者而言任务非常艰巨为什么也导致了一系列的软件兼容问题为什么。2、VLIW设计哲学VLIW的主要思想是将多个相互无依赖的指令封装到一条超长的指令字中CPU中有对应数量的ALU完成相应的指令操作指令之间的依赖性和调度由编译器来完成对于传统的VLIW其特点为一次取多个指令是指令而不是指令bundle记得区分这两个东西具备多个功能部件MIMD架构对于同一个bundle里面的指令而言基于lock step的方式执行后面解释什么是lock step同一个bundle里面的指令静态对齐送给功能单元有了以上的概念我们看一个典型五级流水线与VLIW相结合的例子如下图所示。Bundle包含两条指令因此理想情况下可以实现IPC2。此外我们还可以看出来VLIW通常具有集中的存储器结构以及独立的功能单元。所谓的Lock-step即要么全都带走要么一无所有。只要VLIW中任意一个指令stall住了为了维持并排走的原则所有与之并行的指令都需要停住。有点像两人三足的感觉对于VLIW机器而言是这么处理依赖关系的由编译器处理所有依赖相关的stalls硬件不做任何的依赖检查无条件信任软件如果是可变延时操作又该怎么处理呢Memory堵住了怎么办呢既然VLIW是由软件即编译器处理所有和依赖相关的问题那能够获得的信息就比较少实际上是缺乏运行时硬件信息的因为一旦发出去就没有回头路了由此会有一系列的问题。假设我们取出了某条指令比如a d d t 1 , s 1 , s 2 add\ t1,s1,s2addt1,s1,s2剩下的指令都需要用到t1当做源操作数如果硬件不做任何检查那岂不是一定拿到旧的数据整个就出错了又比如对于同一个程序而言假设我们更换了不同的处理器对于不同的硬件而言功能部件也有可能不同依赖关系自然也不同如果还用之前那一套编译器那结果岂不是有可能对不上没错这些都是VLIW潜在的问题。到目前为止即使我们对VLIW编译器的细节不清楚但我们应该已经领略了VLIW的设计哲学了让我们暂时总结一下VLIW的优点和缺点首先谈一下优点其实优点无非就是硬件设计简单我们具体展开讲讲1、无需动态调度硬件-因此硬件设计起来相对简单。之所以不用动态调度硬件实际上是我们相信编译器所发的指令都是没有依赖关系的因此硬件各自执行各自的不会有任何问题。如果是超标量处理器是需要硬件动态的检查各个指令之间是否存在依赖关系如果有的话可能需要阻塞可能需要旁路可能需要重命名等等这些在VLIW中都不用。静态就是不涉及运行时动态与之相反可以简单的理解硬件跑起来以后提供的信息就是动态信息2、同一个Bundle内的指令天然对齐因此取指令以后直接往功能单元发即可简化了硬件设计然后我们再看一下VLIW的缺点1、编译器需要在每个周期找到N条互相独立的指令组成相应的bundle往功能单元发。如果找不到呢那也只能硬着头皮发总比不发好但这样的话必然某个槽或某几个槽slot比如上面的例子中一个bundle中就有8个slot需要插入NOP指令。这样就减少了并行性并且导致代码size变大总归是要执行完所有指令的插入无意义的指令越多自然总的size就越大。2、当执行宽度Nslot个数、指令延迟、功能单元发生改变的时候都需要重新编译而超标量处理器不需要因此软件兼容性非常差这也是VLIW在通用CPU领域走向失败的根本原因。3、由于Lockstep执行的原因导致某个指令阻塞住了整个bundle都会阻塞住即使它们彼此之间互相独立的。就好像两人三足中队友摔倒了即使你是好好的也需要等待你的队友。VLIW就是这么一套设计哲学将原本硬件应该干的事情全部交给编译器去做这也就导致了编译器开发极为困难因为要通过有限的代码信息去找到互相独立的指令即充分挖掘并行性但很多时候纯靠静态信息并行性是很难挖掘的而编译器为了避免出错**都是按照最保守的方式假设最坏的情况去做**即对似是而非的独立默认不独立这样就会导致大量的NOPs指令。但由于VLIW对硬件设计非常友好因此当并行性非常容易挖掘的时候这种情况编译器开发就没那么困难了比如DSP、GPU、NPU等很多指令天然就是彼此独立的不存在依赖关系的这种场景VLIW就具有非常大的优势。3、干脏活累活的VLIW编译器首先我们看一下VLIW编译器都干了啥通过静态调度尽可能的并行化填满Bundle中的slot保证同一个Bundle内的所有指令是互相独立的必须要保证因为硬件是不会去做检查的通过静态调度尽可能的避免数据冒险因为Lockstep的存在一个堵住了整个就堵住了3.1、循环操作优化当我们谈并行谈VLIW就一定要谈循环级别的并行因为很多时候循环是天然并行的。并且对于编译器而言是很好发现的Loop-Level Parallelism is normally analyzed at the source level or close to it。我们假设编译器无法发现循环的并行性如下图所示可以看到编译以后的汇编代码对于VLIW机器而言可以挖掘的并行性很少并且由于fadd需要用到fld以后的f1做运算因此编译器为了避免出现数据冒险会晚几个周期再送fadd指令到功能组件再强调一次依赖关系由编译器保证这里对应图中的fld-fadd的红线整体的性能非常的差。跑一个浮点加法需要8个周期即使我们认为浮点加是单周期指令。实际上写过C/C的朋友应该都知道这种循环实际上是可以展开的Loop Unrolling就比如下面的例子编译器就可以发现这一点我们假设按照4的粒度进行展开这样就可以在一次循环中执行四次迭代了。当然如果N不是4的整数倍需要把剩下的几次额外处理一下编译器完成该优化以后我们再看展开以后对应的汇编代码以及VLIW机器的流水线占用情况。可以看到流水线排布比之前满了一些整体的FLOPS也有了显著的提高。可不可以进一步提高FLOP实际上是可以的因为我们实际上可以发现两次循环之间是没有依赖关系的即上述的例子中我们原本是0,1,2,3为一组然后4,5,6,7。组与组之间是没有重叠的但实际上它们就是独立的因此可以进一步将它们Overlap起来这称之为Software Pipelineing软件流水线其实跟硬件流水线非常的像本质上没太大区别。如下图所示可能上面的这个VLIW指令排布还不够Makesense我们再看下面这幅图。这幅图相比大家能理解单纯的Loop Unrolled和Software Pipelined的区别了。核心在于Overlapping让独立的东西尽可能重叠起来。3.2、循环之外上面讲的是针对循环并行性的优化如果没有循环呢Josh Fisher在提出VLIW的时候同时也提出了一种名为Trace Scheduling的技术该方法的关键思想是将基本块组合起来使它们形成一个单入口多出口的较大块可能作为直线代码执行。如下图所示此外我们做如下的定义所谓的basic block其实就是一段连续的代码其中没有分支或者跳转指令具有单一的入口和出口由于控制密集型指令的存在比如分支指令basic block的size不可能太大对于单个basic block内部而言很难挖掘出ILP单个Basic block内部认为是顺序执行的指令与指令之间依赖关系较大Trace内部的指令都是单周期指令通过重新安排基本块的顺序使得Trace中的指令尽可能地利用处理器的功能单元同时避免指令之间的冲突和依赖关系进而提高程序的执行效率如下图的灰色路径就是一条Trace实际上Trace对应的是分支或跳转指令执行最频繁的一条路径。我们来看一个实例左边是所有的基本块以及某个基本块到另外一个基本块对应的概率其实就是个决策树。右边是我们根据概率最大选出来的trace是不是非常的清晰但是直接用Trace是有问题的跟踪调度的主要缺点之一是跟踪中间的进入和退出会导致严重的复杂性实际上trace也没有中间进入或退出但实际是的指令是可能有的需要编译器生成和跟踪补偿代码并且通常使得评估此类代码的成本变得困难。 超级块的形成过程与用于跟踪的过程类似但它是扩展基本块的一种形式仅限于单个入口点但允许多个出口。我们直接采取尾部复制的方式就可以实现单入口多出口的superblock大家看下图我们只是在尾部加了F的复制我们可以看到原本C到F以及D到F的入口没了全部转移了。这就是我们所需要的超级块。我们看一下具体的例子左边是原始代码。右边是经过Superblock变换以后的代码通过该机制实现了单入口多出口。下面是Superblock变换以后的代码进一步优化的结果通过更大的代码块有机会找到更多的并行执行机会编译器会相对激进的在superblock内部进行code reorder以及代码优化。总而言之超级块是一种复杂的编译器优化技术需要综合考虑指令之间的依赖关系、处理器的特性和约束条件等因素。它可以在静态编译阶段对程序进行优化以提高程序的执行效率和性能。通过合并基本块并利用指令级并行性超级块可以减少指令之间的冲突和依赖关系从而提高程序的吞吐量和执行效率。这里也只是说了个superblock是什么到底如何根据superblock进行优化优化策略细节就是非常大的话题了涉及到编译器的很多知识这里就不讲了实际上我也不会。4、RISC、CISC和VLIW的区别RISC、CISC和VLIW架构区别架构特征CISCRISCVLIW指令长度变长固定通常32 bits固定指令格式字段布局可变字段布局固定一致字段布局固定一致指令语义指令从简单到复杂变化每条指令可能有许多依赖操作每个指令的语义几乎总是一个简单的操作多数指令是简单、独立的操作寄存器较少部分为专用寄存器较多通用寄存器较多通用寄存器内存引用方式与许多不同类型指令中的操作捆绑在一起不与操作捆绑在一起如Load/Store架构不与操作捆绑在一起如Load/Store架构硬件设计利用微码实现采用单条流水线、不使用微码采用多条流水线、不使用微码和复杂的指令调度逻辑从原理上看一下CISC、RISC和VLIW的区别注意实际上的代码不会是这样的这里只是说明三种架构的区别。一个C语言函数function( long j) { long i; j j I; }CISC代码RISC代码VLIW代码二、SIMD学习1、引入1966年Michael.J.Flynn提出根据指令流、数据流的多倍性特征对计算机系统进行了分类通常称为Flynn分类法有关概念的定义如下。1指令流指机器执行的指令序列。2数据流指由指令流调用的数据序列包括输入数据和中间结果但不包括输出数据。3多倍性指在系统性能瓶颈部件上同时处于同一执行阶段的指令或数据的最大可能个数。Flynn根据不同的指令流和数据流组织方式把计算机系统分成如下4类。1单指令流单数据流Single Instruction stream and Single Data stream,SISD。SISD其实就是传统的顺序执行的单处理器计算机其指令部件每次只对一条指令进行译码并只对一个操作部件分配数据。流水线方式的单处理机有时也被当作SISD.早期的计算机都是SISD机器如冯诺.依曼架构如IBM PC机早期的巨型机和许多8位的家用机等。一条指令处理一个数据项。程序指令按顺序执行每条指令从内存读取或写入一个数据。硬件设计经典的冯·诺依曼架构。包含一个控制单元、一个处理单元、一个内存模块。现代CPU通过流水线、分支预测、多级缓存等技术提高效率但核心执行模型仍是SISD。优点控制简单编程模型直观顺序执行。适合复杂的控制逻辑和任务调度。缺点纯串行无法直接利用数据并行性对大规模数据计算如科学计算、图形处理效率低下。典型代表早期的单核CPU如Intel 8086。2单指令流多数据流Single Instruction stream and Multiple Data stream,SIMD。SIMD以并行处理机阵列处理机为代表并行处理机包括多个重复的处理单元由单一指令部件控制按照同一指令流的要求为它们分配各自所需的不同数据。相联处理机也属于这一类。一条指令同时作用于一组数据一个向量。例如一条“加法”指令完成8对数据的加法。数据级并行硬件设计向量处理器拥有专门的向量寄存器很宽如256/512位和向量功能单元。指令解码后控制器将同一操作广播到多个并行ALU上执行。例如Intel的AVX、ARM的NEON/SVE指令集。阵列处理器由多个相同的处理单元在统一控制下同步工作。优点能效高一条指令解码开销可服务大量数据计算。吞吐量大非常适合规则的数据并行计算如矩阵运算、图像/视频处理、物理模拟。缺点数据对齐要求高。不适合控制密集型或数据依赖性高的任务如分支众多的代码。编程相对复杂需要显式调用特殊指令或编译器自动向量化。典型代表CPU的SIMD指令扩展SSE, AVX早期的Cray超级计算机。3多指令流单数据流Multiple Instruction stream and Single Data stream,MISD。MISD具有n个处理单元按n条不同指令的要求对同一数据流及其中间结果进行不同的处理。一个处理单元的输出又作为另一个处理单元的输入。这类系统实际上很少见到。有文献把流水线看作多个指令部件称流水线计算机是MISD.这是一个理论存在但几乎没有实际商业化应用的模型。概念多个不同的指令同时作用于同一个数据流。硬件设计难以构建实用化的设计。一种解释是容错系统多个处理器执行相同计算以校验结果但指令流可能略有不同严格说也不是纯MISD。另一种是流水线处理数据流经不同阶段执行不同操作但这通常被视为SISD的时空重叠。优缺点缺乏实用案例讨论意义不大。典型代表无广泛认可的商业产品。某些文献将飞行控制中的冗余系统作为例子。4多指令流多数据流Multiple Instruction stream and Multiple Data stream,MIMD。MIMD是指能实现作业、任务、指令等各级全面并行的多机系统。多处理机属于MIMD.当前的高性能服务器与超级计算机大多具有多个处理机能进行多任务处理称为多处理机系统不论是大规模并行处理机还是对称多处理机都属于MIMD.这是任务级并行和数据级并行的通用模型也是现代多核、多处理器系统的主流架构。概念多个处理器/核心独立执行不同的指令流处理不同的数据。硬件设计共享内存多处理器所有核心通过总线或交叉开关共享同一物理内存UMA/NUMA。需要硬件/软件同步机制锁、原子操作。例如多核CPU如Intel Core i7, AMD Ryzen、大型SMP服务器。分布式内存多处理器每个处理器有自己的本地内存通过高速网络互联。通信通过消息传递进行。例如计算机集群、超级计算机。优点灵活性最高可同时处理任务并行不同程序和数据并行同一程序的不同部分。扩展性强可以通过增加节点分布式内存或核心数共享内存来提升性能。缺点通信和同步开销大共享内存存在缓存一致性问题分布式内存存在通信延迟。编程复杂需要处理线程/进程同步、通信、负载均衡等问题如使用Pthreads, OpenMP, MPI。典型代表现代多核CPU、GPU集群、TOP500超级计算机。5SIMT - 单指令流多线程这是NVIDIA GPU采用的核心执行模型是SIMD的一种更灵活、对程序员更友好的变体。概念一条指令被多个线程通常32个为一组称为Warp同时执行。这些线程在同一个程序计数器下运行但拥有自己的寄存器和数据地址。关键点允许同一Warp内的线程有不同的执行路径通过分支但会导致性能下降线程分化。硬件设计流多处理器SM包含多个标量处理核心、共享内存/缓存、寄存器堆。Warp调度器负责将32个线程打包成一个Warp进行调度和执行。如果所有线程走相同路径效率接近SIMD如果分支会串行执行不同路径。优点相对于传统SIMD编程模型更灵活程序员以多线程的角度思考CUDA/OpenCL硬件负责将线程分组和调度隐藏了底层SIMD宽度。更好地处理不规则并行和分支虽然分化有代价但模型本身支持。拥有层次化的存储结构寄存器、共享内存、全局内存便于优化数据局部性。缺点线程分化和内存访问非对齐/不连续会显著降低实际吞吐量。需要大量线程来隐藏内存访问延迟。不适合任务并行或控制密集型任务。典型代表NVIDIA GPU的CUDA架构AMD GPU的GCN/RDNA架构也采用类似思想。总结与异同对比架构核心思想并行粒度硬件关键特征编程模型/难点主要应用场景SISD一次一指令一数据指令级非真正并行单核复杂控制单元顺序编程简单直观通用计算控制密集型任务SIMD一次一指令多数据数据级并行宽向量寄存器多ALU受控于同一指令需数据对齐避免分支媒体处理科学计算规则算法SIMT一次一指令多线程数据级并行线程级呈现Warp调度标量核心阵列层次化存储大规模多线程CUDA需避免Warp分化GPU通用计算图形渲染AI训练/推理MISD多指令一数据理论模型无实用主流难以有效实现无主流编程模型特殊容错或信号处理极少MIMD多指令多数据任务级与数据级并行多独立核心共享或分布式内存线程/进程同步与通信OpenMP/MPI多核CPU、服务器、超级计算机2、SIMD架构在学习SIMD之前我们首先需要了解两个概念。浮点运算指令分为两大类Packed矢量 和Scalar标量。Packed指令是一次对寄存器中的四个浮点数即DATA0 ~ DATA3均进行计算而Scalar一次则只对寄存器中的DATA0进行计算。如下图所示SIMD 的工作依赖于向量寄存器这些寄存器可以存储多个数据元素。例如如果一个寄存器宽度是 128 位并且每个数据元素是 32 位的整数那么该寄存器一次就可以存储 4 个整数。在 SIMD 操作时一条指令对这 4 个整数同时执行相同的计算如加法、乘法等。2.1 整体架构┌─────────────────────────────────────────────┐ │ 控制单元 (Control Unit) │ │ 取指→解码→广播→向量寄存器控制→存储控制 │ └──────────────┬──────────────────────────────┘ │ 广播相同操作 ▼ ┌─────────────────────────────────────────────┐ │ 向量处理单元阵列 │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ ALU │ │ ALU │ │ ALU │ │ ALU │ ... │ │ │ 0 │ │ 1 │ │ 2 │ │ 3 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ │ │ │ └──────┼────────┼────────┼────────┼───────────┘ │ │ │ │ ┌──────┼────────┼────────┼────────┼───────────┐ │ ┌───▼──┐┌───▼──┐┌───▼──┐┌───▼──┐ │ │ │向量寄││向量寄││向量寄││向量寄│ ... │ │ │存器 0││存器 1││存器 2││存器 3│ │ │ │(通道0)│(通道1)│(通道2)│(通道3)│ │ │ └──────┘└──────┘└──────┘└──────┘ │ │ 向量寄存器文件 │ └─────────────────────────────────────────────┘ │ │ │ │ ┌──────┼────────┼────────┼────────┼───────────┐ │ 内存加载/存储单元 (Load/Store Unit) │ │ 支持对齐访问、跨步访问、聚集/散播 │ └─────────────────────────────────────────────┘2.2 详细组件说明2.2.1 向量寄存器文件 (Vector Register File)结构特点宽寄存器128/256/512/1024位宽度多通道每个寄存器划分为多个通道(lane)数量通常16-32个向量寄存器数据组织text256位向量寄存器示例 ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐ │ 通道0 │ 通道1 │ 通道2 │ 通道3 │ 通道4 │ 通道5 │ 通道6 │ 通道7 │ │ 32位 │ 32位 │ 32位 │ 32位 │ 32位 │ 32位 │ 32位 │ 32位 │ └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘2.2.2 处理单元阵列 (Processing Element Array)并行ALU设计多个相同的ALU并行工作每个ALU处理一个数据通道操作数来自向量寄存器的对应通道结果写回向量寄存器的对应通道功能单元类型算术单元加法器、乘法器、乘加单元(FMA)逻辑单元与、或、非、移位比较单元产生掩码(mask)特殊函数单元倒数、平方根等2.2.3 控制单元 (Control Unit)SIMD指令解码识别向量指令操作码确定操作数宽度和数量生成控制信号广播到所有处理单元广播机制标量广播将标量值复制到所有通道立即数广播将立即数复制到所有通道寄存器广播将向量寄存器的一个元素广播到所有通道2.2.4 内存子系统 (Memory Subsystem)对齐访问要求数据地址对齐到向量宽度非对齐访问需要特殊处理性能损失访问模式支持text1. 连续访问 (Contiguous) 内存[A0][A1][A2][A3][A4][A5][A6][A7] 加载一次性加载8个连续元素 2. 跨步访问 (Strided) 内存[A0][X][A1][X][A2][X][A3][X] (stride2) 加载每隔一个元素加载 3. 聚集-散播 (Gather-Scatter) 内存[A0][B0][C0][D0][A1][B1][C1][D1] 索引[0][4][8][12][16][20][24][28] 聚集根据索引从不同位置收集数据 散播根据索引分散数据到不同位置