Branch Runahead: An Alternative to Branch Prediction for Impossible to Predict Branches
介绍论文原文
tage-sc-l分支预测器在大多数问题上都有很高的准确率,但是对于数据依赖型的分支却无能为力。例如判断一个数组中的某个数据是否为0,它依赖于数组的值,现有分支预测器都是基于过去分支的历史进行的,二者没有相关性,因此无法预测。
本文提出了一种提前执行分支指令的方法,通过一个小的处理器提前计算出分支结果,来处理分支预测器无法预测数据依赖型分支的问题
依赖链的计算守护分支和影响分支想要提前计算出分支指令,首先需要知道哪些指令和这个分支指令相关。这里首先需要给出两个定义
守护分支(Guard branch): 守护分支会决定另外的分支是否执行。例如两层的if,如果外层的if不执行,那么内层的if也不会执行,这时外层的if就是守护分支
影响分支(affector branch): 影响分支是可以影响其他分支源数据的分支。
要获得守护分支和影响分支首先需要知道分支正确路径和错误路径的合并点。由于现代乱序多发射的结构导致一次预测错误会多取上百条错误指令,因此可以使用正确路径的指令和错误路径的指令来找到两条路径的合并点。
守护分支的确定很简单,任何出现在合并点之前的分支都可以认为是 ...
gpu存储架构
本篇是《通用图形处理器设计-GPGPU编程模型与架构原理》的阅读笔记
gpu处理器架构
gpu存储结构简介
gpu存储和cpu截然不同,呈现倒三角的结构。gpu使用如此多的寄存器文件主要是为了线程束的零开销切换。因为每个线程束都有它自己的寄存器,因此每次切换线程束时就不需要像cpu线程切换时那样将寄存器存入内存再读取了。
大容量寄存器带来的一个负面影响是L1和L2缓存的容量被大量挤压,在Pascal架构中超过60%的片上存储容量被分配给了寄存器。在NVIDIA V100架构中每个核最多128kb的l1数据缓存容量,而每个核中最多有2048个线程,也就是说每个线程只能分配到64b的空间。而l2缓存的容量有6mb,远小于l1数据缓存共10mb的容量。
寄存器gpu处理器的高并行导致每个核需要大量的寄存器端口。例如如果同时执行32个线程,每次需要读取3个操作数,那么要求寄存器文件每周期需要提供96个32bit的读端口和32个写端口。而寄存器在存储中占了绝大部分比重,大量的资源消耗导致寄存器无法使用激进的多端口设计。gpu中往往使用多bank的单端口来模拟多端口的设计。
如图所示为多板块寄存 ...
gpu核心结构
本篇是《通用图形处理器设计-GPGPU编程模型与架构原理》的阅读笔记
基础gpu基础结构可以参照
在上面已经提到线程块调度器会将线程块发送给对应的处理器,而处理器将执行线程块中所有线程。但是线程网格和线程块都是用户指定的,而硬件资源是有限的,例如寄存器端口,执行单元数量等。如果线程块的数量过大,那么执行一条指令就需要很多周期的时间,而且不好调度。因此处理器中真正的调度单位是线程束,线程束的大小是根据硬件资源决定的,线程块传递给处理器时会自动将线程块划分成若干线程束。
线程束中所有线程的pc相同,即执行的指令相同,不同的是他们有不同的线程id,读寄存器时会根据线程id和寄存器id来获得寄存器值。如果将它看成向量处理器,那么线程束就是单个指令流,每个线程只是一个分量。
每一个处理器中都会同时存在大量线程束,通过快速切换线程束执行来隐藏访存等耗时操作的延迟。
GPU指令流水线
gpu流水线和cpu类似,分为取指,译码,调度,读寄存器,执行,写回等阶段。
取指和译码在gpu中由于同时存在多个线程束且每个线程束的执行进度不一致,因此取指单元中需要保存多个pc值,然后调度单元根据线程束的状态选 ...
tage分支预测器
介绍tage分支预测器论文
tage-sc-l分支预测器
tage分支预测器是现代高性能处理器中常用的预测器,他使用pc和全局历史作为输入,通过哈希得到index和tag进行查表,并且谨慎的只更新少数表来减少表项的占用。在一些测试集中可以达到95%以上的准确率且低于5MKPI
预测tage分支预测器由一个base表和多个tage表组成。
base表是一个类gshare预测器,使用pc的哈希作为index。
tage表由三个部分组成,tag,u和ctr。其中ctr为饱和计数器。使用pc和不同长度的全局历史查表
tage表的查表方式为将pc和n位的全局历史使用不同的哈希函数分别获得index和tag,然后使用index获得表中的某一项表项,再使用tag进行匹配表项中的tag,如果匹配成功则使用表项中的饱和计数器作为最终结果。
如果有多个表成功匹配,则将最长历史的表的结果作为最终结果,如果全部没有匹配,则使用基础预测器作为最终结果
在实现时,如果历史长度较短,则可以直接将历史异或,进行折叠来获得index和tag。如果历史长度较长,则可以选择历史中的某几位和上一步计算结果进行逻辑操作来生成 ...
简截
简介简截是一款截图软件。它的主要功能是图片透明化。
透明化前
透明化后
此外他还支持多种截图模式并且可以图片上编辑
下载及代码
所有版本
最新版本(密码8nq4)
文档
github地址页
欢迎拿走源码自己修改。也可以在评论区提意见(我设置了邮箱提醒)。
功能介绍
支持开机自启,自动更新,历史记录保存,自动复制到剪切板等功能
多区域截图
滚动截图
使用opencv库的图像拼接实现,并且加上了多线程,位置在Capture_window/…/Scroll_handle。
此外滚动截图可以调整滚动速度。滚动速度较快时可以利用所有cpu。
![](https://xinhecuican.tech/images/简截8.gif)
绘制 当前仅支持笔,荧光笔和文本绘制,并且支持撤销、恢复和擦除。
透明
目前仅可以做到对某一个色素透明,对于渐变和拍屏无效。并且由于文字都是由不同种类像素组成因此无法做到选取文字(正好下学期有图像处理,看看通过反锯齿可以直接把文字的范围弄出来)。
oc ...
自动操作使用说明
自动操作是一款基于无障碍服务的安卓软件,可以提供自动点击,滚动,条件跳转等操作。
启用
首先点击设置按钮开启无障碍服务及关闭电源优化,然后开启服务,只有在开启服务后才能进行后面的设置。
悬浮球用于需要手动启动的配置,可以在配置页选择配置,然后点击悬浮球开始自动操作
配置添加配置
如图所示点击右下角的+号可以新建配置。点击配置右侧的三个点可以进入配置页面,长按进行删除和置换位置。点击可以选择下次触发的配置
修改配置
页面可以简单理解为应用,当切换应用时会同时检测当前页面的配置,如果发现有自启动的配置将会自动运行配置
配置是由一个个的操作组成的,进行完上一个操作之后会自动进行下一个操作,在配置页面中运行操作的顺序是从上到下。
点击步骤右侧的加号可以添加操作,共有如下五种操作。添加后点击图标可以进行操作的配置页面
所有配置都有重复次数和延迟两个属性。延迟表示在上一个操作结束之后需要等待多长时间才进行该操作。其中每一个操作图标下面的数字表示延迟
点击操作
点击操作可以根据屏幕的绝对坐标,控件,文本进行点击。
控件点击: 如下图所示,控件是无障碍服务可以操作的部分。使用控件进行点击的优点 ...
遗传算法
理解遗传算法思路来源于基因进化。即基因会随机突变,复制(生出新个体),最终适应的种群将会繁衍(找到最优解)。本质上是一种并行的搜索算法,可以自适应的得到最优解。
因此遗传算法的几个关键点是定义突变,复制过程,定义搜索空间和如何选择优良个体(定义适应度)
过程
随机的创建种群(例如二维搜索中随机的创建搜索点)
定义适应函数(二维搜索中和终点的距离)
选择出适应的个体作为父母进行繁衍
通过交叉和复制产生后代:从父亲和母亲中抽取一部分特征作为子集并合并,另一部分直接复制优秀的父亲和母亲
对一些个体进行变异
def nextGeneration(currentGen, eliteSize, mutationRate): popRanked = rankRoutes(currentGen) selectionResults = selection(popRanked, eliteSize) matingpool = matingPool(currentGen, selectionResults) children = breedPopulation(matingpool ...
recast navigation
简介recast navigation是基于三角形网格的寻路系统,他相比四边形网格可以减少网格数量从而提高网格速度。它具体可以分为两部分,recast和detour。recast是构建寻路网格的过程,detour是利用网格寻路的过程
recast过程划分参考
具体构建过程是根据Sample_SoloMesh.cpp中的handleBuild
体素化在体素化阶段,mesh将被转化成体素(一个个小的长方体)。
体素化的目的是填充heightfield的span区域,span是一个二维数组,长和宽是包围盒内体素的长和宽。而每一个span是rcSpan*类型,他是一个链表,链接竖直方向的体素
构建过程:
rcAllocHeightfield:new一个rcHeightfield实例
rcCreateHeightfield: 初始化rcHeightfield
rcMarkWalkableTriangles: 根据传进来的mesh(顶点和三角形)计算出哪个三角形可以通过。具体方法为计算每个三角形的法线,如果法线角超过设定值则认为不可通过
rcRasterizeTriangles(rcCon ...
寻路算法
深度优先和广度优先可以参考这篇文章
a*算法可以参考这篇文章
b*算法b*搜索相对于a*搜索速度快了几十倍,但是他不能够保证最优解,和贪心算法有些类似。
定义:
探索节点:起始探索节点为原点
自由探索节点: 还可以进行下一步的探索节点
绕爬探索节点: 如果前方有阻挡,探索节点将试图绕过阻挡,绕行中的探索节点称为绕爬节点
算法过程:
起始,探索节点为原点,向目标进发
自由节点在前进过程中判断前方是否有障碍
有障碍,则分出左右两个分支试图绕过障碍,绕过障碍后节点将变成自由节点
无障碍,向目标前进一步
bool map[boundary.height()][boundary.width()];// 初始化map为0// 第二个参数为父节点Node* begin_node = new Node(point, null);map[point.x][point.y] = 1;begin_node->direction = getDirection(begin_node, end_node);free_nodes.push(begin_node); // 自由节点while(!fr ...
autotools使用
基本流程
基本流程为:
使用autoscan生成configure.scan文件,然后重命名为configure.acconfigure.ac里面包含一些自动检查的内容
执行aclocal,configure.ac中的宏实际上是m4宏的一个封装,这条命令将会吧ac宏解析成m4宏
执行autoconf, 它会生成configure脚本
执行autoheader,它会根据configure.ac中的内容生成一些预定义信息
Makefile.am中包含了程序编译链接信息,也就是makefile的主体内容,执行automake会生成Makefile的前置文件
执行./configure会生成Makefile文件
configure是检查系统设置,库函数是否满足等运行环境判断,Makefile.am则是真正的进行编译
configure.acautoconf基于此
首先介绍m4,m4是一个宏处理器,它会扫描文本,如果遇到宏则将其展开。
我们可以简单的认为他将shell脚本套上了一层函数的壳,例如:
// 检测是否安装foo程序的shellif [ $(which foo) ]then ...