gpt4 book ai didi

performance - VM设计:更多操作码还是更少操作码?什么是更好的?

转载 作者:行者123 更新时间:2023-12-03 11:58:17 24 4
gpt4 key购买 nike

不要震惊。这是很多文本,但是我担心如果不提供一些详细的信息,我将无法真正显示出这是怎么回事(并且可能会得到很多答案,而这些答案并没有真正解决我的问题)。而且这绝对不是一项任务(就像有人在他的评论中荒谬地声称的那样)。

先决条件

由于除非设置了至少一些先决条件,否则可能根本无法回答此问题,因此以下是先决条件:

  • 将解释虚拟机代码。禁止存在JIT编译器,但设计应针对解释器。
  • VM应该基于寄存器,而不是基于堆栈。
  • 答案可能既不假定存在一组固定的寄存器,也不假定存在无限数量的寄存器,情况可能是这样。

  • 此外,我们需要更好地定义“更好”。必须考虑以下两个属性:
  • 磁盘上VM代码的存储空间。当然,您总是可以在此处放弃所有优化,而只是压缩代码,但这对(2)产生负面影响。
  • 解码速度。如果将代码转换为可以直接执行的代码花费的时间太长,那么存储代码的最佳方法就是无用的。
  • 内存中的存储空间。无论是否进行进一步的解码,此代码都必须可以直接执行,但是如果涉及进一步的解码,则在执行期间和每次执行指令时都要进行此编码(将代码计数加载到项目2时,解码仅执行一次)。
  • 代码的执行速度(将常见的解释器技术考虑在内)。
  • VM的复杂性以及为其编写解释器的难度。
  • VM自身所需的资源量。 (如果VM运行的代码大小为2 KB,并且执行速度比眨眼时快,那不是一个好的设计,但是这样做需要150 MB的空间,并且其启动时间远远超过代码的运行时间。它执行)

  • 现在通过更多或更少的操作码来说明我实际上的意思。看起来好像实际上已设置了操作码数,因为每个操作需要一个操作码。但是,这并不容易。

    相同操作的多操作码

    您可以进行类似的操作
    ADD R1, R2, R3

    将R1和R2的值相加,然后将结果写入R3。现在考虑以下特殊情况:
    ADD R1, R2, R2
    ADD R1, 1, R1

    这些是在许多应用程序中可以找到的常见操作。您可以使用已经存在的操作码来表示它们(除非您需要其他操作码,因为最后一个操作码具有int值而不是寄存器)。但是,您也可以为这些创建特殊的操作码:
    ADD2 R1, R2
    INC R1

    和之前一样。优势在哪里? ADD2只需要两个参数,而不是3,INC甚至只需要一个参数。因此,这可以在磁盘和/或内存中进行更紧凑的编码。由于将任何一种形式转换为另一种形式也很容易,因此解码步骤可以在两种表达方式之间转换。我不确定哪种形式都会影响执行速度。

    将两个操作码合并为一个

    现在,假设您有ADD_RRR(R为寄存器)和LOAD来将数据加载到寄存器中。
    LOAD value, R2
    ADD_RRR R1, R2, R3

    您可以拥有这两个操作码,并在整个代码中始终使用这样的结构...,也可以将它们组合成一个新的操作码,命名为ADD_RMR(M用于内存)
    ADD_RMR R1, value, R3

    数据类型与操作码

    假设您有16位整数和32位整数作为本机类型。寄存器为32位,因此任何一种数据类型都适合。现在,当您添加两个寄存器时,可以使数据类型成为参数:
    ADD int16, R1, R2, R3
    ADD int32, R1, R2, R3

    例如,对于有符号和无符号整数也是如此。这样,ADD可以是一个简短的操作码,一个字节,然后您有另一个字节(或者可能只是4位)告诉VM如何解释寄存器(它们保存16位还是32位值)。或者,您可以取消类型编码,而是使用两个操作码:
    ADD16 R1, R2, R3
    ADD32 R1, R2, R3

    有人可能会说两者完全相同-只是将第一种方式解释为16位操作码可以工作。是的,但是一个非常幼稚的口译员看起来可能大不相同。例如。如果每个操作码都有一个函数并使用switch语句进行分派(dispatch)(这不是最好的方法,函数调用开销,switch语句也可能不是最佳的),那么这两个操作码可能看起来像这样:
    case ADD16: add16(p1, p2, p3); break; // pX pointer to register
    case ADD32: add32(p1, p2, p3); break;

    并且每个功能都围绕某种添加。第二个可能看起来像这样:
    case ADD: add(type, p1, p2, p3); break;

    // ...
    // and the function

    void add (enum Type type, Register p1, Register p2, Register p3)
    {
    switch (type) {
    case INT16: //...
    case INT32: // ...
    }
    }

    将子交换机添加到主交换机,或将子调度表添加到主调度表。当然,无论类型是显式的还是非显式的,解释器都可以采用任何一种方法,但是根据操作码设计,开发人员会觉得每种方法都更加原生。

    元操作码

    由于缺乏更好的名字,我会这样称呼他们。这些操作码本身完全没有意义,它们只是改变了后面的操作码的含义。就像著名的WIDE运算符一样:
    ADD R1, R2, R3
    WIDE
    ADD R1, R2, R3

    例如。在第二种情况下,寄存器是16位的(因此您可以添加更多的寄存器),在第一种情况下,寄存器只有8位。否则,您不能具有这样的元操作码,而不能具有ADD和ADD_WIDE操作码。像WIDE这样的元操作码可以避免使用SUB_WIDE,MUL_WIDE等,因为您总是可以在所有其他普通操作码之前加上WIDE(总是只有一个操作码)。缺点是操作码本身就变得毫无意义,无论是否为元操作码,您都必须先检查该操作码。此外,VM必须为每个线程存储一个额外的状态(例如,是否现在处于宽模式),并在下一条指令后再次删除该状态。甚至CPU都有这样的操作码(例如x86 LOCK操作码)。

    如何找到一个好的折衷方案???

    当然,您拥有的操作码越多,切换/调度表就会变得越大,在磁盘或内存中表达这些代码所需的位数也就越多(尽管您可以在没有数据的磁盘上更有效地存储它们)必须由VM直接执行);虚拟机也将变得更加复杂并具有更多的代码行-另一方面,操作码的功能也更加强大:您越来越接近每个表达式(甚至是一个复杂的表达式)都将以一个操作码结尾的地步。

    选择少量的操作码可简化对VM的编码,并导致非常紧凑的操作码-另一方面,这意味着您可能需要大量的操作码来执行简单的任务,并且每个不经常使用的表达式都必须成为某种(本机)函数调用,因为它无法使用任何操作码。

    我读了很多关于Internet上所有类型的VM的文章,但没有一种资料能真正做出良好而公平的权衡。设计VM就像设计CPU,有些CPU的操作码很少,它们运行很快,但是您还需要许多。而且,有些CPU的操作码很多,有些很慢,但是表达相同的代码所需的CPU却少得多。看起来“越多的操作码越好” CPU完全赢得了消费者市场,而“越少的操作码越好”的CPU只能在服务器市场或 super 计算机业务的某些部分生存。虚拟机呢?

    最佳答案

    老实说,我认为这很大程度上取决于VM的用途,类似于处理器的设计在很大程度上取决于处理器的主要使用方式。

    换句话说,您最好能够确定VM的常见用例场景,以便您可以建立可能需要的功能,并建立不太可能需要的功能。

    我当然知道,您可能正在设想一个抽象的,非常通用的虚拟机,该虚拟机可以用作其他编程语言的内部/后端实现?

    但是,我认为,重要的是要意识到并强调,实际上没有任何事物的“通用理想”实现,即一旦使事物保持通用和抽象,您将不可避免地面临需要做出妥协的情况。

    理想情况下,这些折衷方案将基于您的代码的实际使用场景,因此这些折衷方案实际上是基于充分了解的假设和简化而来的,您可以毫不犹豫地进行。

    换句话说,我会考虑您的VM的目标是什么?
    它主要如何在您的视觉中使用?
    您要实现的目标是什么?

    这将帮助您提出要求并帮助您进行简化,以便您可以基于合理的假设来设计指令集。

    如果您希望您的VM主要被编程语言用于数字运算,那么您可能希望通过提供许多低级原语并支持广泛的数据类型,为数学运算寻找一个相当强大的基础。

    另一方面,如果您将服务器作为OO语言的后端,则需要考虑优化相应的低级指令(即哈希/字典)。

    通常,我建议一开始就使指令集尽可能简单直观,并且仅在证明适当的位置确实有用(即配置文件和操作码转储)并且确实会导致性能下降时,才添加特殊指令。获得。因此,这很大程度上取决于您的VM拥有的第一个“客户”。

    如果您真的很想研究更多涉及的方法,您甚至可以考虑在运行时动态优化指令集,使用模式匹配在字节码中查找操作码的常见出现,从而派生出更多的抽象实现,以便您可以进行转换您的字节码与运行时生成的自定义操作码一起动态生成。

    关于performance - VM设计:更多操作码还是更少操作码?什么是更好的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/972438/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com