並聯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引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

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

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

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

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