计算机体系结构:VLIW

news2024/10/7 5:31:51

原文来自知乎 计算机体系结构:VLIW

本文主要介绍计算机体系结构中的VLIW,以供读者能够理解该技术的定义、原理、应用。

🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:计算机杂记
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!

目录

1、引言

2、VLIW设计哲学

3、干脏活累活的VLIW编译器

3.1、循环操作优化

3.2、循环之外

4、总结


1、引言

在开始之前,我们思考一下,怎么才能够让一个程序执行得更快?在计算机领域当中有一个非常经典的公式来计算一个程序的执行时间。

根据上面的式子可以看出来,有三个因素影响了程序的执行时间。

  • 该程序总共需要执行的指令个数;
  • 每条指令所需要的周期数(简称CPI)
  • 每个周期所对应的时间;

本篇文章围绕CPI展开,CPI全称Clock Per Instruction,即每个时钟周期能够执行的指令个数,它反映了处理器并行处理指令个数的能力。有时候我们也用其倒数形式,即IPC(Instruction Per Clock)。

对于非流水线的多周期处理器,我们需要多个Cycle才能执行完一条指令,对于普通的流水线处理器,我们一个周期最多也就执行一条指令,IPC最大也就只能为1了,还有没有办法让IPC进一步提高呢?

实际上在程序的指令流中,很多指令相互之间是独立的,只要处理器有足够的硬件资源,理论上它们就可以被同时执行,即实现指令级别的并行(ILP,Instruction Level Parallesim),最典型的ILP有以下几种方式:

  • 流水线(有时候提ILP不会提流水线,因为处理器设计默认采用流水线);
  • 超标量(Superscalar);
  • 超长指令字(Very Long/Large Instruction Word,VLIW);

超标量处理器设计是个非常大的话题,也是目前高性能CPU的主流技术。本篇文章不讨论超标量处理器,而是围绕VLIW展开,去思考为何VLIW曾一时风光无限,又为何在通用处理器市场败下阵来,又是怎么在DSP/NPU等领域重新大放异彩的,带着这些问题,我们正式进入VLIW的学习。

VLIW于1983年由美国计算机科学家Josh Fisher提出,并发表于体系结构顶会ISCA上,根据VLIW的名字我们就可以知道,其指令一定很长。实际也确实如此。

VLIW是将多条互相独立的指令,通过软件(编译器)的方式打包(Pack)在一起,我们将打包好的多条指令,称为instruction bundle。取指模块根据打包好的指令,送入各自独立的功能部件,并行执行,如下图所示,取指模块从指令存储器取出了Instruction Bundle,共包含四条指令,然后同时发送给后级模块,从而实现了指令级并行。

此外我们可以看出来其一共有两个浮点部件、三个整数部件、两个存储部件、一个转移部件,因此对应的指令Bundle长度为32*8=256。

根据上面的例子我们不难发现,指令一旦送出以后,各个功能部件是互相独立的,各个指令也是天然并行的。即VLIW不需要通过硬件检查指令与指令之间的依赖关系,而是由软件(编译器)去静态的调度互相独立的指令,其优点就是硬件设计将对简单(为什么?),但对于编译器开发工作者而言,任务非常艰巨(为什么?),也导致了一系列的软件兼容问题(为什么?)。

2、VLIW设计哲学

对于传统的VLIW而言,其一般具有以下的特性:

  • 一次取多个指令(是指令,而不是指令bundle,记得区分这两个东西),具备多个功能部件(MIMD架构);
  • 对于同一个bundle里面的指令而言,基于lock step的方式执行(后面解释什么是lock step);
  • 同一个bundle里面的指令静态对齐,送给功能单元;

有了以上的概念,我们看一个典型五级流水线与VLIW相结合的例子,如下图所示。Bundle包含两条指令,因此理想情况下可以实现IPC=2。此外我们还可以看出来,VLIW通常具有集中的存储器结构,以及独立的功能单元

所谓的Lock-step,即要么全都带走,要么一无所有。只要VLIW中任意一个指令stall住了,为了维持并排走的原则,所有与之并行的指令都需要停住。(有点像两人三足的感觉)

对于VLIW机器而言,是这么处理依赖关系的:

  • 由编译器处理所有依赖相关的stalls;
  • 硬件不做任何的依赖检查(无条件信任软件);
  • 如果是可变延时操作又该怎么处理呢?Memory堵住了怎么办呢?

既然VLIW是由软件即编译器处理所有和依赖相关的问题,那能够获得的信息就比较少,实际上是缺乏运行时(硬件)信息的,因为一旦发出去,就没有回头路了,由此会有一系列的问题。

假设我们取出了某条指令,比如add $t1,$s1,$s2,剩下的指令都需要用到$t1当做源操作数,如果硬件不做任何检查,那岂不是一定拿到旧的数据?整个就出错了?

又比如对于同一个程序而言,假设我们更换了不同的处理器,对于不同的硬件而言,功能部件也有可能不同,依赖关系自然也不同,如果还用之前那一套编译器,那结果岂不是有可能对不上?没错,这些都是VLIW潜在的问题。

到目前为止,即使我们对VLIW编译器的细节不清楚,但我们应该已经领略了VLIW的设计哲学了,让我们暂时总结一下VLIW的优点和缺点:

首先谈一下优点,其实优点无非就是硬件设计简单,我们具体展开讲讲:

1、无需动态调度硬件->因此硬件设计起来相对简单。之所以不用动态调度硬件,实际上是我们相信编译器,所发的指令都是没有依赖关系的,因此硬件各自执行各自的,不会有任何问题。如果是超标量处理器,是需要硬件动态的检查各个指令之间是否存在依赖关系,如果有的话,可能需要阻塞,可能需要旁路,可能需要重命名等等,这些在VLIW中都不用。(静态就是不涉及运行时,动态与之相反,可以简单的理解,硬件跑起来以后提供的信息就是动态信息)

2、同一个Bundle内的指令天然对齐,因此取指令以后直接往功能单元发即可,简化了硬件设计;

然后我们再看一下VLIW的缺点:

1、编译器需要在每个周期找到N条互相独立的指令,组成相应的bundle往功能单元发。如果找不到呢?那也只能硬着头皮发,总比不发好,但这样的话,必然某个槽或某几个槽(slot,比如上面的例子中,一个bundle中就有8个slot)需要插入NOP指令。这样就减少了并行性,并且导致代码size变大(总归是要执行完所有指令的,插入无意义的指令越多,自然总的size就越大)。

2、当执行宽度(N,slot个数)、指令延迟、功能单元发生改变的时候,都需要重新编译(而超标量处理器不需要),因此软件兼容性非常差,这也是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、总结

看完本篇文章,大家应该也清楚VLIW为什么会在通用处理器领域失败了,其实无非就是软硬件没有充分解耦,对编译器开发要求过高,软件兼容性太差。并且在通用CPU领域,纯靠静态信息可挖掘的并行性不够,会插入很多NOPS指令,实际的性能打不过超标量+乱序处理器。

但VLIW的硬件设计简单,对于使用场景具有大量并行性的处理器,如DSP、GPU、部分NPU等,VLIW都在大放异彩,感兴趣的可以搜相关论文看,本篇文章就讲到这里,希望对大家有所帮助,如果有错误欢迎指正。

🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!

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

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

相关文章

8套成熟在用的三级医院信息化系统源码,HIS、LIS、PACS、智慧导诊、线上预约挂号支付系统源码

8套成熟在用的二级医院、三级医院医院管理系统源码,均有自主知识产权,应用案例,系统稳定运行中。可直接上手项目,支持二次开发 ▶ 一、SaaS模式Java语言开发的云HIS系统源码 在公立二甲医院应用三年,融合B/S版电子病历…

[项目设计] 从零实现的高并发内存池(四)

🌈 博客个人主页:Chris在Coding 🎥 本文所属专栏:[高并发内存池] ❤️ 前置学习专栏:[Linux学习] ⏰ 我们仍在旅途 ​ 目录 6.内存回收 6.1 ThreadCache回收内存 6.2 CentralCache回收内存 Rele…

Docker安装+基础命令

一、检测、配置安装环境 (1)查看linux版本,是否符合>centos 7 (2)查看网络是否通畅 (3)安装gcc,gcc-c编译器 (4)安装device-mapper-persistent-data和lvm2…

【LabVIEW FPGA】CIC滤波器

一、CIC滤波器应用概述 在通信数字信号上下变频时,经常会用到对数字信号的升采样和降采样,即通过CIC数字速率器实现变采样率。 二、滤波器IP 首先设置滤波器基本参数(filter specification) 滤波器类型(Filter Type…

2024年阿里云域名优惠口令更新,亲测有效口令大全

2024年阿里云域名优惠口令,com域名续费优惠口令“com批量注册更享优惠”,cn域名续费优惠口令“cn注册多个价格更优”,cn域名注册优惠口令“互联网上的中国标识”,阿里云优惠口令是域名专属的优惠码,可用于域名注册、续…

【图形学中的数学】GAMES001

目录 0 引言1 线性代数基础1.1 向量(Vector)1.2 向量空间(Vector Space)1.3 线性组合1.4 图形学研究的维度1.5 矩阵(Matrix)1.5.1 矩阵单目运算1.5.2 低维变换矩阵 1.6 齐次坐标 🙋‍♂️ 作者&…

使用数据库实现增删改查

#include<myhead.h>//定义添加数据函数int do_add(sqlite3 *ppDb) {//1.准备sql语句,输入要添加的信息int add_numb; //工号char add_name[20]; //姓名char add_sex[10]; //性别double add_score; //工资printf("请输入要添加的工号:")…

leetcode 热题 100_最大子数组和

题解一&#xff1a; 动态规划&#xff1a;这是一道经典的动态规划题。维护一个dp数组&#xff0c;dp[i]表示0~i组成的数组的最大子数组和。当数组长度为1时&#xff0c;最大和连续子数组是它本身&#xff0c;也就是dp[i]nums[i]。当数组长度每增加1时&#xff0c;最大和连续子数…

每日力扣——滑动窗口与前 K 个高频元素

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害。 滑动窗口最大值 给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑…

开展庆2024年“三八”国际妇女节系列纪念活动怎样向媒体投稿?

为了向媒体投稿,庆祝2024年“三八”国际妇女节系列纪念活动,你可以遵循以下步骤: 策划与准备: 确定纪念活动的主题和目标,例如提升女性权益、表彰女性成就、促进性别平等。 策划一系列活动,如研讨会、表彰仪式、展览、讲座等,确保内容丰富多样。 准备相关的背景资料、活动介…

DR模式下LVS负载均衡聚集部署实验

目录 1、实验准备 2、配置负载调度器&#xff08;ens33&#xff1a;192.168.80.9 VIP:192.168.80.188&#xff09; 2.1 配置虚拟ip地址&#xff08;VIP&#xff1a;192.168.80.188&#xff09; 2.2 调整proc响应参数 2.3 设置负载分配策略 3、部署共享存储&#xff08;NF…

Win11桌面出现的这个图标“了解此图片”怎么关闭?

&#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力&#x1f609; 在csdn获奖荣誉: &#x1f3c6;csdn城市之星2名 ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ …

代码随想录刷题笔记-Day29

1. N皇后 51. N 皇后https://leetcode.cn/problems/n-queens/ 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数…

《金三银四求职攻略》:程序员面试季倒计时

程序员的金三银四求职宝典 大家好&#xff0c;我是小明&#xff0c;一位即将面临春季求职季的程序员。在这个黄金时段&#xff0c;如何在众多应聘者中脱颖而出&#xff0c;拿下理想的offer&#xff0c;成为了我思考的重点。今天&#xff0c;我将分享一些我个人的求职攻略&…

Python(NetOps)前传-网络设备开局配置

背景 我们知道用Python在cli配置网络设备的前提是&#xff1a; 网络设备与Python主机网络可达网络设备已开启并完成ssh相关配置 目标 本文已华为S5720S-52P-LI-AC交换机为例&#xff0c;完成&#xff1a; 完成网络设备开局配置&#xff1b;用Python脚本验证ssh登录 配置 …

【爬虫】单首音乐的爬取(附源码)

以某狗音乐为例 import requests import re import time import hashlibdef GetResponse(url):# 模拟浏览器headers {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0}# 发送请求…

[动态规划]---part2

前言 作者&#xff1a;小蜗牛向前冲 专栏&#xff1a;小蜗牛算法之路 专栏介绍&#xff1a;"蜗牛之道&#xff0c;攀登大厂高峰&#xff0c;让我们携手学习算法。在这个专栏中&#xff0c;将涵盖动态规划、贪心算法、回溯等高阶技巧&#xff0c;不定期为你奉上基础数据结构…

Stable Diffusion WebUI API http://127.0.0.1:7860/docs空白

在尝试调用Stable Diffusion WebUI API的时候&#xff0c;打开http://127.0.0.1:7860/docs遇到了以下页面 网络诊断是这样的原因&#xff1a; 修bug&#xff0c;改来改去遇到了以下两种页面&#xff1a; 此时http://127.0.0.1:7860可以如下正常显示&#xff1a; 查资料的时候找…

小白跟做江科大51单片机之DS1302按键可调时钟

1.引入上一个程序的代码 2.引入Key和Timer0文件 3.获取按键值 定义全局变量unsigned char keynum main函数中 keynumKey(); 4.设置第一个按键的两种模式&#xff0c;以此来控制时钟的设定和显示 if(keynum1) { if(MODE0) { …

机器视觉相关网站推荐

机器视觉相关网站推荐 - 知乎计算机视觉&#xff08;Computer Vision&#xff09;最近这几年发展迅速&#xff0c;技术论坛和QQ群也如雨后春笋&#xff0c;特别是人脸检测/识别领域。近段时间云从君从研究院那里探得了好几个论坛&#xff0c;收藏了若干网站&#xff0c;记录下&…