並聯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)

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。
