WebGL, WebCL 及多核:在浏览器中使用 River Trail 实现并行 JavaScript 的现状与未来

  • W. Schuster
  • D. Synodinos
  • 蔡坚安

2011 年 11 月 28 日

话题:JavaScriptHTML5语言 & 开发

现在连移动设备都具备了并行处理能力,但 JavaScript 仍然是串行的。Intel 实验室正在着力创建 JavaScript 的一项扩展,该扩展会利用多核系统优势,并已发布了 Firefox 插件。InfoQ 对来自 Intel 实验室的 Stephan Herhut 进行了关于这项工作的独家采访。

这种开发代码为 River Trail 的 JavasScript 扩展是 Intel 实验室的一个项目,该项目致力于将 Intel 多核 CPU 的处理能力以及向量扩展(vector extension)应用于 web 应用程序中。River Trail 正努力使计算密集型(compute intensive)应用程序——如图像编辑软件——能在浏览器中运行。

River Trail 使用确定性数据并行结构对 JavaScript 进行扩展,该结构在运行时会被转换到底层硬件抽象层。通过调控多个 CPU 核心与向量指令,River Trail 将大大提高并行 JavaScript 的性能。。

值得注意的是,River Trail 在 JavaScript 中添加了 ParallelArray 数据类型,这是存储真实并行数组数据的只读数据结构。我们可以用 JavaScript 数组,类型化的数组,或用于产生并行数组数据的函数来创建并行数组。例如,“new ParallelArray([1,2,3])”将创建一个存储数值 1,2,3 的并行数组。该数组的内容能够被combinefiltermapreduce等对数据进行并行处理的函数访问。分配给它们的 JavaScript 函数会编译成 OpenCL。这些函数能够使用 JavaScript 的一个子集。

InfoQ 对来自 Intel 实验室的 Stephan Herhut 进行了关于这项工作的独家采访。

InfoQ:请问开发 River Trail 项目的动因是什么?

Stephan:该项目开始的时候我还不在 Intel,所以我问了参与这项工作的 Rick Hudson,这个项目是如何开始的?他说:

“因为我们相信可以对多核程序和向量指令系统进行简化,从而提高编程人员——特别是使用 JavaScript 的 web 应用开发人员——的生产力。向 web 应用开发人员提供高性能和高生产力的结构是个棘手的问题,同时也是激励我们的原因之一。”

我在年初就参与了这个项目,真正使我感到兴奋的是 River Trail 非常符合 HTML5 技术。有很多问题限制了 web 应用能够具有内建应用所具有的功能,HTML5 解决了很多方面的问题。然而,谈到性能时,web 应用仍然有很大的差距。浏览器厂商在提高 JavaScript 引擎性能方面已经做了很多工作。当我在内建 JavaScript 中看到 broadway h.264 这样的解码器时非常惊讶。然而,JavaScript 基本上是串行的。WebWorker 允许后台长延时处理,但对于并行计算来说过重。River Trail 解决了数据并行处理的问题,我们在 GitHub 上的原型证明了这是一种可行的方法。

InfoQ:你认为与直接编写 OpenCL 代码相比,使用 JavaScript 作为输入语言的关键优势是什么?

Stephan:这个问题涉及两个方面:一是对 web 开发者来说有什么好处,二是对 JavaScript 引擎开发者以及对浏览器来说有什么好处?

对 web 开发者来说,我相信最大的好处就是易于使用:他们不需要学习一门新语言,能够继续使用他们熟悉的编程环境。RiverTrail 建立在已有的 JavaScript 概念之上,比如数组,map 和 reduce 函数,作为函数参数的闭包等等。在 River Trail 中并没有新的语言结构。所以,很多情况下开发者能直接在 Reiver Trail 上重用他们的代码。他们需要将 for 循环替换成 River Trail 的基本类型,比如 map,仅仅如此而已。实际的实现方式通常不需要变化,至少我们希望如此。我们目前的项目原型还不能做到这样,但我相信我们最终能实现。

问题的另一个方面是对引擎开发者来说有什么好处?最大的好处就是安全性。浏览器是一个主要的攻击入口,而用户希望浏览器能提供安全的上网体验。OpenCL 是为客户端应用程序设计的,用户通常会从安全的地方得到安装程序。它基本上是 C 语言的翻版,具有 C 语言一样的功能和安全问题。因此,JavaScript 是被设计成在 web 上使用的语言,来自 web 的代码通常不可信。我们坚持这样的设计原理,即 River Trail 使用和序列化执行同样的安全机制,比如数组边界检查。

另外一个问题是普遍性。web 应用程序运行在许多不同的平台和设备上,从笔记本到手机都有。在这些平台上 JavaScript 普遍存在,但 OpenCL 也许不存在。River Trail 在浏览器 JavaScript 引擎上的内建实现可以将 RiverTrail 代码转换成向量化的机器码。即使完全序列化的执行也是有效的。API 都是经过精心设计的,很具有一般性,允许有许多不同的实现方式。

InfoQ:存在不能用 JavaScript 语法来表达的 OpenCL 代码吗?JavaScript 缺乏类型声明不会出现问题吗?

Stephan:我们从来没有把 RiverTrail 成 web 版的 OpenCL。只是我们恰巧在项目原型中使用了 OpenCL 作为后台技术。RiverTrail 使用了更高层次的抽象。因此,我们并不支持底层 OpenCL 特性,比如本地内存共享,同步屏障或工作组。这些特性是 OpenCL 才应该有的,但并不适合 River Trail 这样高层的 API。类型问题并没有我们所想的那样大。首先,WebGL 引进的类型化数组已经能让程序员操纵 JavaScript 中的数据存储方式。这已经一定程度上在我们的 River Trail 项目原型中采用了。其次,JIT 引擎在优化数据表示上越来越强大。JavaScript 类型推断的研究取得了不错的进展,目前能推断出哪些计算最好在哪些类型中执行。RiverTrail 顺其自然地受益于这些进展。

InfoQ:有可能在某些地方将 River Trail 和 WebCL 一同使用吗?如果这样的话,可以保留一个纯 JavaScript 的版本吗?比方说不需要内建 OpenCL 库的版本?另一个想法是整合 WebCL 和 WebGL。好像 River Trail 能够从 Canvas 中获取位图数据,但好像它是在 OpenCL 内存之间来回复制的。通过整合 WebGL 和 WebCL,有可能可以获取 WebGL 数据,用 WebCL 进行处理(使用 River Trail 产生的核心),然后再将数据转移到 WebGL,而不用将它复制回浏览器内存。

Stephan:我们决定实现自己的 Firefox 浏览器扩展完全是由于历史原因。当我们开始 Reiver Trail 工作的时候还不存在 WebCL,而当 WebCL 出现后我们已经实现了自己的接口。该接口相当于 WebCL 的简化版本。在 GitHub 上有一个 River Trail 的分支项目,该项目使用 WebCL 作为后台实现,而不使用我们的 Firefox 浏览器扩展。但我不确定该项目是否支持在 WebCL 和 WebGL 之间进行缓存共享。我现在关注的重点是从 web 开发者那里了解 River Trail 是否符合他们的需求,然后根据他们的反馈改进 API。我欢迎有人能开发一个基于 WebCL 的版本,并乐于提供帮助。我很有兴趣看看这种方式能有怎样的改进潜力。

InfoQ:你们目前支持什么样的 JavaScript 语言结构?你们计划提供更多的支持吗?

Stephan:我们在 GitHub 上的项目原型是对概念的验证,也是我们对语言特性的实验。目前,我们只支持基本数据数组。我们虽然也支持内嵌数组,但要求其具有最简单的形式,例如,我们将 canvas 中的图像数据构建成具有 4 个元素向量的矩阵。另一个限制是我们不支持对全局数值的引用和在内核中的函数调用。这些限制大多数是由于我们的原型不是在 JavaScirpt 引擎内实现的。相反,我们的编译器是用 JavaScript 语言编写的,并运行在 JavaScript 引擎之上。此方式能让我们迅速地构建原型特征,但限制了我们访问引擎的内部信息。SpiderMonkey 正在进行将更多内核信息暴露到脚本层的工作,一旦此工作完成,我们会看看是否能再消除掉一些限制。但最终来讲,River Trail 应该直接成为 JavaScript 引擎的一部分。

InfoQ:OpenCL 目标语言对于你们提供 JavaScript 特性支持有哪些限制呢?

Stephan:最大的限制就是堆管理。OpenCL 要求我们显式地将那些我们要从内核中访问的 JavaScript 堆映射到 OpenCL 堆。这就是我们目前只支持基本类型密集数组的原因之一。要完全支持内嵌数组和任意对象的数组,须要遍历和深入地复制底层数据结构。这在 CPU 上执行是不可行也没有必要的。

InfoQ:关于数值,你们将 JavaScript AST 中的所有数值都转换成双精度浮点型吗?还是你们会区分双精度浮点型和整型?(例如:‘x = 42’会被转换成整型吗?)

Stephan:JavaScript 语义要求所有计算都应在 64 位浮点上进行。但我们通常不需要这样高的精度,River Trail 允许 web 开发者指定在内核执行时使用 32 位浮点。除此之外,我们已经实现了一系列分析,用以推断在整型上计算是否安全。在循环边界判断上通常就是这样。对于你的例子,如果我们的编译器能证明对 x 的连续写操作能保持在 32 位整型值范围之内,‘x = 42’就会使 x 作为整型存储。如果我们不能验证这样做的稳定性,那么 x 就会作为单精度浮点型或双精度浮点型存储。

InfoQ:ParallelArray 目前是 River Trail 提供的主要抽象。你们有提供其它抽象的想法吗?或者说所有的任务都能被映射成 ParallelArray 吗?

Stephan:ParallelArray 抽象非常符合数据并行负载。并行编程的另一个有趣主题就是任务并行负载。分而治之的样式算法也在这个主题之内。webworker 也有同样的特性,但它们过于复杂,同时也不支持状态共享。我还不知道确切答案,但任务并行是个值得研究的领域。

InfoQ:在 web 开发者可以直接调控 GPU 和多个 CPU 核的情况下,你认为 web 应用在不久的将来会有什么样的进步?

Stephan:我自己不是 web 开发者,但我非常敬佩他们的创造力。当看到 Chrome 和 Mozilla 的 WebGL 示例出现的时候,我坐在我的笔记本前感到非常惊讶。所以很难预料将来会发展成什么样。在功能上,web 应用将会越来越像内建应用,但在其它方面又会有很大的不同。web 应用最大的优势就是它们的连接性。它们可以使用不同的数据源,将数据进行整理,实时地更新数据,用很炫的视觉效果展现数据。我希望 web 能变得更具有渗透性,而不仅仅是以页面为中心。我能肯定的是我将会为 web 开发者创造出来的东西感到震惊。

InfoQ:该项目接下来的计划是什么?

Stephan:我们目前正在努力提高原型的适用范围,同时正在探索如何尽可能地完全支持 JavaScript。其中一部分工作就是将 River Trail 直接引进 JavaScript 引擎。我们正在与 Mozilla 合作将 RiverTrail 整合进它们的下一代 JavaScript 引擎,同时我们也欢迎与其它浏览器引擎的合作。还有另外一项重要的工作就是处理用户反馈。最终,我们希望 RiverTrail 成为 JavaScript 的一部分,作为一项开放标准。我们想保证它确实能满足 web 开发者的需求以及他们关注的可用性。我们想依靠 web 社区来完成这些事情。请玩玩 RiverTrail,用它构建新玩意,并将意见反馈给我们。

查看英文原文:WebGL, WebCL, MultiCores: The State and Future of Parallel Javascript in the Browser with RiverTrail

JavaScriptHTML5语言 & 开发