- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我最近在这里阅读了这个问题 Why is it faster to process a sorted array than an unsorted array?并找到了绝对令人着迷的答案,它完全改变了我在处理基于数据的分支时对编程的看法。
我目前有一个相当基本但功能齐全的解释型英特尔 8080 仿真器,它是用 C 语言编写的,操作的核心是一个 256 长的 switch-case 表,用于处理每个操作码。我最初的想法是,这显然是最快的工作方法,因为操作码编码在整个 8080 指令集中并不一致,解码会增加很多复杂性、不一致和一次性情况。充满预处理器宏的 switch-case 表非常简洁且易于维护。
不幸的是,在阅读上述帖子后,我突然想到我计算机中的分支预测器绝对无法预测 switch case 的跳跃。因此,每次导航 switch-case 时,管道都必须被完全删除,导致几个周期延迟,否则这个程序应该是一个非常快的程序(我的代码中甚至没有乘法)。
我敢肯定你们中的大多数人都在想“哦,这里的解决方案很简单,转向动态重新编译”。是的,这看起来确实会削减大部分开关盒并显着提高速度。不幸的是,我的主要兴趣是模拟旧的 8 位和 16 位时代的控制台(这里的英特尔 8080 只是一个例子,因为它是我最简单的模拟代码),其中周期和时间保持准确的指令很重要,因为视频和声音必须根据这些确切的时间进行处理。
当处理这种级别的准确性时,性能成为一个问题,即使对于较旧的控制台也是如此(例如,看看 bSnes)。在处理具有长流水线的处理器时,是否有任何追索权或这只是一个事实?
最佳答案
相反,switch
语句很有可能被转换为jump tables ,这意味着它们可能会执行一些 if
(用于范围检查)和一次跳转。 if
不应导致分支预测出现问题,因为您不太可能有错误的操作码。跳转对流水线不是很友好,不过到头来,整个switch
语句,就这么一个..
我认为您无法将较长的操作码 switch
语句转换为任何其他可带来更好性能的形式。当然,前提是您的编译器足够聪明,可以将其转换为跳转表。如果没有,您可以手动执行此操作。
如有疑问,请实现其他方法并衡量绩效。
首先,请确保您不会混淆 branch prediction和 branch target prediction .
分支预测仅适用于分支语句。它决定分支条件是失败还是成功。它们与跳转语句无关。
另一方面,分支目标预测试图猜测跳跃的终点。
因此,您的陈述“分支预测器无法预测跳跃”应该是“分支目标预测器无法预测跳跃”。
在您的特定情况下,我认为您实际上无法避免这种情况。如果你有一个非常小的操作集,也许你可以想出一个涵盖所有操作的公式,就像在逻辑电路中所做的那样。然而,对于与 CPU 一样大的指令集,即使它是 RISC,该计算的成本也远高于单次跳转的代价。
关于c - 在 CPU 仿真中使用 switch case 时如何处理分支预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11668090/
我对虚拟机的 CPU 虚拟化有疑问。我无法理解即时到 native 代码翻译与陷阱和模拟翻译之间的区别。 据我所知,在第一种情况下,假设我从不同的平台模拟二进制代码,如果我有 x86 CPU,代码将转
我对虚拟机的 CPU 虚拟化有疑问。我无法理解即时到 native 代码翻译与陷阱和模拟翻译之间的区别。 据我所知,在第一种情况下,假设我从不同的平台模拟二进制代码,如果我有 x86 CPU,代码将转
我必须模拟 Ant 在它们的家(黑框)和食物(黄框)之间移动。这些三色盒子是 Ant 。我为绘制所示图形编写的代码如下: % background background() % making
我有一些使用 java.awt.Color 的代码。我想将我的 Java 代码转换为 GWT。所以我将在我的 GWT 项目中模拟 java.awt.Color。 一种方法是编写一个名为源路径为awt的
大家好圣诞节快乐我需要一个建议我有以下代码: int main() { int k=5000000; int p; int sum=0; for (p=0;p<
假设您有一个 Simulink 仿真,其中某个信号首先为正,然后在给定时间间隔内经过一段时间 t 后变为负。您的目标是找到零交叉点。 第一种方法是在给定的间隔内绘制信号,保存它并计算过零。 当针对不同
现在是周末,所以我通过编写一个爱好项目来放松整周的编程。 昨天写了一个MOS 6502 CPU仿真器的框架,寄存器、堆栈、内存和所有操作码都实现了。 (来源链接如下) 我可以在我编写的调试器中手动运行
出于测试目的,我需要创建如下所示的 AVD: 但是我所有的模拟设备都是这样的: 它们只包含屏幕,没有硬件键盘。这是“新设备”对话框: “存在硬件键盘”没有任何效果。如何获得所需的设备配置? Andro
有没有什么地方有一个独门绝技的小马,它可以使 css3 的所有优点(阴影、发光、圆 Angular )并使其与 ie6 兼容/看起来相似... i have try that ...哦,天哪,这太丑了
在用 c++ 实现“super”之前,我正在寻找一种自己模拟它的方法。动机:这是一个典型的场景: class A { void SomeMethod(); } class B : public
我正在研究一个模拟 QEMU 设备来模拟 FPGA PCIe 接口(interface)。我使用 lev-pci 设备作为基本模板: https://github.com/levex/kernel-q
您知道为 Windows 和/或 Linux 制作软件(虚拟)HID 设备的方法吗? 我想将一些传感器用作 HID,但它们没有任何 HID,所以我想我可以在 PC(模拟 onde)上安装自己的 HID
我很确定这个问题的答案是否定的,但万一有一些 PHP 大师 是否有可能以可以传入无效参数或不存在的变量的方式编写函数,并且 php 在不使用 '@' 的情况下不会出错 很像 empty 和 isset
当 Kinect 本身未插入时,是否可以模拟 Kinect 传感器(用于与 Kinect SDK 一起使用)? 起初我认为 Kinect Studio 完全符合我的要求,但现在看来 Kinect St
我已经搜索了 1 个多小时没有成功。是否有模拟框架集的纯 CSS 方式?我的意思是,真的在模仿它。我发现了一些有趣的东西,您将在其中固定顶部和底部 block ,但内容的滚动条是常规的浏览器主体滚动条
是否存在用于编程需求的虚拟 GPIO 驱动程序? 我必须在我的 Linux PC 上开发一个软件,然后在一些带有物理 GPIO 的嵌入式系统(C.H.I.P.、OpenWRT 等等......)上试用
我正在尝试开始 Android 开发。 我在 Linux 上使用 eclipse 并使用 Pentium IV @3.2Gh 和 1GB 内存。我刚刚遵循“hello android”howto,只有
我使用 Google Chrome 和 Intern 运行自动化测试,我想知道是否有办法从 CLI 以仿真模式启动 Chrome 或使用特定标志来测试移动渲染。如果没有,您知道一个好的解决方法吗? 我
我正在尝试通过 STM32F1 上的闪存模拟 EEPROM,如 here 所述(对于STM32F4)例如,但我正在努力更改STM32F1RB(中密度)规范的代码。我正在使用 SW4STM32、Cube
使用下面的测试代码,我尝试使用 中的 simulator 通过 xmega128a3u 的 USART 发送数据Atmel Studio. 观察 I/O 查看数据寄存器从未设置,即使我正在设置它。是我
我是一名优秀的程序员,十分优秀!