并联JavaScript
ParallelJS:优雅的Web Worker解决方案
ParallelJS为使用Web Worker时可能出现的问题提供了一种优雅的解决方案,它提供了一个具有便捷抽象和辅助工具的实用API。HTML5引入的Worker接口允许创建具有较长运行时间和高计算量需求的函数,这些函数可以同时使用以提高网站响应速度。ParallelJS允许对JavaScript代码进行并行化处理,利用同时多线程 (SMT) 更有效地使用现代CPU。ParallelJS库提供诸如spawn
、map
和reduce
等方法,分别用于并行执行计算、处理数据和聚合碎片化结果。
HTML5带来的一个最酷的新可能性是Web Workers API的Worker接口。在此之前,我们不得不采用一些技巧来向用户展示响应迅速的网站。Worker接口允许我们创建具有较长运行时间和高计算量需求的函数。此外,Worker实例可以同时使用,使我们能够根据需要生成任意数量的这些工作器。在本文中,我将讨论为什么多线程很重要,以及如何使用ParallelJS在JavaScript中实现它。
为什么需要多线程?
这是一个合理的问题。从历史上看,生成线程的能力提供了一种优雅的方式来划分进程中的工作。操作系统负责调度每个线程的可用时间,这样优先级更高、工作量更大的线程将优先于低优先级的空闲线程。在过去的几年里,同时多线程 (SMT) 已经成为访问现代CPU计算能力的关键。原因很简单:摩尔定律在每单位面积晶体管数量方面仍然有效。然而,由于多种原因,频率缩放不得不停止。因此,必须以其他方式使用可用的晶体管。人们决定,架构改进(例如SIMD)和多核代表最佳选择。
为了使用SMT,我们需要编写并行代码,即为获得单个结果而并行运行的代码。我们通常需要考虑特殊的算法,因为大多数顺序代码要么很难并行化,要么效率非常低。原因在于Amdahl定律,该定律指出加速比S由下式给出:
其中N是并行工作器的数量(例如处理器、核心或线程),P是并行部分。将来可能会使用更多依赖于并行算法的多核架构。在高性能计算领域,GPU系统和特殊架构(例如英特尔至强Phi)代表了此类平台。最后,我们应该区分一般的并发应用程序或算法和并行执行。并行性是(可能相关的)计算的同时执行。相反,并发是独立执行进程的组合。
JavaScript中的多线程
在JavaScript中,我们已经知道如何编写并发程序,即使用回调函数。现在可以将此知识转移到创建并行程序中!根据其自身的结构,JavaScript是在由事件循环(通常遵循反应器模式)调解的单个线程中执行的。例如,这为我们处理对(外部)资源的异步请求提供了一些很好的抽象。它还保证先前定义的回调始终在相同的执行线程中触发。没有与线程相关的跨线程异常、竞争条件或其他问题。但是,这并没有让我们更接近JavaScript中的SMT。随着Worker接口的引入,已经找到了一个优雅的解决方案。从主应用程序的角度来看,Web Worker中的代码应被视为并发运行的任务。通信也是以这种方式进行的。我们使用消息API,该API也可用于从包含的网站到托管页面的通信。例如,以下代码通过向发起者发送消息来响应传入的消息。
window.addEventListener('message', function (event) { event.source.postMessage('Howdy Cowboy!', event.origin); }, false);
理论上,Web Worker也可以生成另一个Web Worker。但是,实际上大多数浏览器禁止这样做。因此,Web Worker之间通信的唯一方法是通过主应用程序。通过消息进行的通信是并发进行的,因此只有异步(非阻塞)通信。起初,这在编程中可能很奇怪,但它带来了许多优点。最重要的是,我们的代码应该没有竞争条件!让我们来看一个使用两个参数表示序列的开始和结束来在后台计算素数序列的简单示例。首先,我们创建一个名为prime.js的文件,其中包含以下内容:
onmessage = function (event) { var arguments = JSON.parse(event.data); run(arguments.start, arguments.end); }; function run (start, end) { var n = start; while (n < end) { var k = Math.sqrt(n); var found = false; for (var i = 2; !found && i <= k; i++) { found = n % i === 0; } if (!found) { postMessage(n.toString()); } n++; } }
现在,我们只需要在主应用程序中使用以下代码来启动后台工作器即可。
if (typeof Worker !== 'undefined') { var w = new Worker('prime.js'); w.onmessage = function(event) { console.log(event); }; var args = { start : 100, end : 10000 }; w.postMessage(JSON.stringify(args)); }
相当多的工作。尤其令人讨厌的是使用另一个文件。这产生了很好的分离,但对于较小的任务似乎完全是多余的。幸运的是,有一种解决方法。考虑以下代码:
var fs = (function () { /* code for the worker */ }).toString(); var blob = new Blob( [fs.substr(13, fs.length - 14)], { type: 'text/javascript' } ); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); // Now setup communication and rest as before
当然,我们可能希望有一个比这样的幻数(13和14)更好的解决方案,并且根据浏览器,必须使用Blob和createObjectURL的回退。如果您不是JavaScript专家,fs.substr(13, fs.length - 14)的作用是提取函数体。我们通过将函数声明转换为字符串(使用toString()调用)并删除函数本身的签名来做到这一点。
ParallelJS能帮上忙吗?
这就是ParallelJS发挥作用的地方。它为一些便利以及Web Worker提供了一个不错的API。它包括许多辅助工具和非常有用的抽象。我们首先提供一些要处理的数据。
var p = new Parallel([1, 2, 3, 4, 5]); console.log(p.data);
data字段产生提供的数组。还没有调用任何“并行”操作。但是,实例p包含一组方法,例如spawn,它将创建一个新的Web Worker。它返回一个Promise,这使得使用结果变得轻而易举。
window.addEventListener('message', function (event) { event.source.postMessage('Howdy Cowboy!', event.origin); }, false);
上面代码的问题是计算不会真正并行。我们只创建一个单个后台工作器,它一次性处理整个数据数组。只有在处理完整个数组后,我们才能获得结果。更好的解决方案是使用Parallel实例的map函数。
onmessage = function (event) { var arguments = JSON.parse(event.data); run(arguments.start, arguments.end); }; function run (start, end) { var n = start; while (n < end) { var k = Math.sqrt(n); var found = false; for (var i = 2; !found && i <= k; i++) { found = n % i === 0; } if (!found) { postMessage(n.toString()); } n++; } }
在前面的示例中,核心非常简单,可能过于简单。在一个真实的示例中,将涉及许多操作和函数。我们可以使用require函数包含引入的函数。
if (typeof Worker !== 'undefined') { var w = new Worker('prime.js'); w.onmessage = function(event) { console.log(event); }; var args = { start : 100, end : 10000 }; w.postMessage(JSON.stringify(args)); }
reduce函数有助于将碎片化的结果聚合到单个结果中。它提供了一个方便的抽象,用于收集子结果并在知道所有子结果后执行某些操作。
结论
ParallelJS为我们提供了一种优雅的方式来规避使用Web Worker时可能出现的问题。此外,我们获得了一个包含一些有用抽象和辅助工具的不错的API。将来可以集成进一步的改进。除了能够在JavaScript中使用SMT之外,我们可能还想使用矢量化功能。如果支持,SIMD.js似乎是一种可行的方法。在某些(希望不会太遥远的)将来,使用GPU进行计算也可能是一个有效的选项。在Node.js中存在CUDA(一种并行计算架构)的包装器,但是仍然无法执行原始JavaScript代码。在那之前,ParallelJS是我们充分利用多核CPU处理长时间运行计算的最佳选择。你呢?你如何使用JavaScript释放现代硬件的强大功能?
关于使用ParallelJS的并行JavaScript的常见问题解答 (FAQ)
什么是ParallelJS,它是如何工作的?
ParallelJS是一个JavaScript库,允许您通过利用多核处理器来并行化数据处理。它的工作原理是创建一个新的Parallel对象并将一个数据数组传递给它。然后可以使用.map()
方法并行处理此数据,该方法将指定的函数应用于数组中的每个项目。然后在新的数组中返回结果。
如何安装ParallelJS?
可以使用npm(Node.js包管理器)安装ParallelJS。只需在终端中运行命令“npm install paralleljs”。安装完成后,您可以使用“var Parallel = require('paralleljs');”在您的JavaScript文件中引用它。
使用ParallelJS的好处是什么?
ParallelJS允许您充分利用多核处理器进行数据处理任务。这可以大大加快大型数据集的处理时间。它还提供了一个简单直观的API,使并行化代码变得容易。
我可以在浏览器中使用ParallelJS吗?
是的,ParallelJS可以在浏览器中使用。您可以使用脚本标签和ParallelJS文件的URL将其包含在HTML文件中。包含后,您可以像在Node.js中一样使用Parallel对象。
如何在ParallelJS中使用.map()
方法?
ParallelJS中的.map()
方法用于将函数应用于数据数组中的每个项目。该函数作为字符串传递给.map()
方法。然后在新的数组中返回结果。例如,“var p = new Parallel([1, 2, 3]); p.map('function(n) { return n * 2; }');”将返回一个值为[2, 4, 6]的新数组。
ParallelJS中的.reduce()
方法是什么?
ParallelJS中的.reduce()
方法用于使用指定的函数将数据数组减少为单个值。该函数作为字符串传递给.reduce()
方法。例如,“var p = new Parallel([1, 2, 3]); p.reduce('function(a, b) { return a b; }');”将返回值6。
我可以在ParallelJS中链接方法吗?
是的,ParallelJS中的方法可以链接在一起。例如,您可以使用.map()
方法处理数据,然后使用.reduce()
方法将结果组合成单个值。
如何在ParallelJS中处理错误?
可以使用.catch()
方法处理ParallelJS中的错误。此方法接受一个函数,如果在处理过程中发生错误,则会调用该函数。错误对象将传递给此函数。
我可以将ParallelJS与其他JavaScript库一起使用吗?
是的,ParallelJS可以与其他JavaScript库一起使用。但是,您需要确保使用.require()
方法将库包含在worker上下文中。
ParallelJS适用于所有数据处理任务吗?
虽然ParallelJS可以大大加快大型数据集的处理时间,但它可能并非所有任务的最佳选择。对于小型数据集,创建worker和传输数据的开销可能超过并行化的益处。最好使用您的具体用例测试ParallelJS,以查看它是否提供了性能优势。
以上是并联JavaScript的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务
