【发布时间】:2011-12-06 14:28:12
【问题描述】:
我正在用 Javascript 实现图灵机(将其视为虚拟机)。我正在制定一个尽可能高效地执行计算的例程(这不是项目从一开始就关注的重点)。
是的,除非遇到性能问题,否则我不应该考虑优化。但是我正在做的事情的性质(大多数非平凡的程序都有非常低效的渐近运行时)意味着总会有一些东西可以从优化中获得。我想尽我所能每秒获得尽可能多的指令(合理)。
例如,如果我使用 C++ 编程,解决方案就很清楚了。做一些时间安排。 gprof。 -O3 等。我将研究我希望代码在其上运行的架构,并且可能还会查看正在生成的程序集。
但不能用 javascript 做到这一点。我的第一直觉是将内部循环中的操作减少为数组查找。在我看来,如果解释器能够将 CPU 缓存性能转换为(希望是短的)一系列整数运算,那么我将能够利用 CPU 缓存性能是一个不错的选择。
图灵机非常简单。它实际上是存在的最简单的计算公式(!):它具有有限数量的状态,双向无限磁带,可以在任一方向移动一个单元的磁带头,并且可以读取和写入单个字符到磁带。
一个程序被编码在一个转换函数中,该函数接受一个状态和一个读取的字符,并利用该信息提供要写入的字符、移动头部的方向和新状态。
这是每一步的逻辑:
// states is an array of arrays of triplets and is the transition func
var trans = states[state][alph_index[tape[pos]]];
tape[cur_tape_pos] = trans[0]; // write
cur_tape_pos += trans[1]; // move
state = trans[2]; // state update
这个过程发生在一个循环中。我似乎很清楚磁带将是一个数组。我想将值存储(附加)到数组的末尾至少是使用 Javascript 数组的摊销常数时间操作。附加到数组前面也有很好的性能还不太清楚,所以我可能想要使用两个数组,一个向左延伸,一个向右延伸。
问题是,在幼稚的实现中会在内部循环中插入一个条件语句。我不喜欢那样。无论如何,必须已经有条件检查来检查状态是否为停止状态。所以也许它不会那么糟糕。
还有一种潜在的优化可以消除对alph_index 的索引,方法是将索引存储在字母表中,而不是将字母表值本身存储在磁带上。
但主要问题是这个。我还能做些什么来让它更快?有可能让它更快吗?我不知道执行的哪个组件将成为瓶颈(CPU 或 I/O,或其他什么?),我不知道如何才能找到它。使用 Javascript,我也可以使用哈希表,但似乎数组总是会更快。
也许我过早地寻求建议。随着我的进步,我会回来编辑性能数据。
作为对阅读我的问题的奖励,我将提供一个链接,指向我的项目的实时正在进行的版本:http://stevenlu.net/tm.html
到目前为止,它的操作是操纵一个充满spans 的div,它代表磁带。它还对字符串执行大量操作,并且还对元素进行大量复制,这在涉及图灵机的实际计算时是完全不必要的。但即便如此,它也取得了不错的表现。在我的机器上花了大约一分钟来计算 600,000 步左右 (5^4 = 625),即每秒 10,000 步。这还不错,但我知道我可以通过一些较低级别的编程实现每秒超过一百万。
查看上一代 CPU 的 benchmark perf here,我看到每个内核大约 10,000 MIPS。因此,我估计,如果我可以在运行 50 次 Dhrystone 迭代的时间内运行一次内部循环(即使我不知道这些综合基准实际上做了什么,这对于简单的 C 实现来说似乎很有可能),除非内存带宽限制,我在一个线程上每秒有 2 亿次迭代。我的 600k 步计算将在 3ms 内完成!!
好吧,如果我可以让我的 5^4 计算在浏览器不向我报告它已挂起的情况下运行,我会很高兴...
更新
随着算法的更高效的 javascript 实现完成,9^4 = 6561 的计算需要 58202209 步,计算时间为 6173 毫秒。那是每秒 940 万步。比我原来的 DOM 依赖方法增加了近 1,000 倍。
最初的5^4 计算(即使不滚动磁带也需要大约 30 秒)现在在 84 毫秒内完成。
【问题讨论】:
-
我喜欢 DOM 图灵机 :)
-
谢谢 :) 我已经投入了很多工作,我喜欢用 javascript 编程。看看我的俄罗斯方块游戏stevenlu.net/tetris.html
-
为什么不能分析 JavaScript?如果您在浏览器中运行它,Chrome 会内置它。 Ctrl-shift-C,点击 Profiles,然后开始 CPU profiling...
-
@BobG,很高兴知道。虽然我试过了,但它并没有显示很多有用的信息:主要是
100% for (program) -
嗯,对于 CS 学生来说,这绝对是一个很酷的玩具。我喜欢滚动磁带!
标签: javascript arrays performance optimization