2014-01-22 60 views
2

Hy,我正在開發一個webgl應用程序,它需要生成大量的2d幾何,例如折線,複雜的多邊形。目前使用的頂點/顏色/索引/ texcoords被預先分配,然後根據主更新循環內的用戶輸入進行計算。WebGL,優化web工作幾何計算

我嘗試儘可能地回收,例如。當繪製150000個圓時,我會嘗試確保幾何體/顏色/ texcoords /指標僅計算一次,除非基本參數(圓形細節,...)不更改,然後平移,縮放(x & y),旋轉此「圓形藍圖」的頂點(將指數&設置頂點顏色),乘以用戶指定的量。
之後數據通過一個drawArrays/drawElements調用發送。繪製多段線和其他基元的處理過程與此類似。雖然這已經非常快,但顯然花了很多時間將原始頂點轉換爲新的位置和維度,有時候只留下少量的用戶可以用來實際構建的東西顯示的資源。
所以我問自己,我怎麼可以外包這些簡單的計算。在考慮採用gpgpu的方式之前,我曾考慮將這些計算轉移給網絡工作者。

所以這是我腦子裏想的:

  1. 主線:用戶發送請求,繪製150000圈,提供的尺寸,轉換和顏色
  2. 主線程:請求推到了一個平局請求隊列
  3. 主線程:請求數據發送給Web工作人員(如果工作人員未啓動或已完成上一個隊列項目)
  4. Web工作人員:正在使用足夠大的預分配的一組數據truct幾何形狀和改造它
  5. 網絡工作者:傳遞變換Float32Array頂點,通過 轉讓對象的顏色數據和Uint16Array索引數據的主線程
  6. 主線:onWorkeRequestProcessed:獲得的數據由工人發送,發送到調用glDrawArrays/glDrawElements呼叫, 將數據發送回給工人
  7. 網絡工作者:接收回數據,發送「OK,寄託都放回原處,我已經準備好爲另一請求」 MSG到主線程
  8. 主線程:移隊列,從前面發送下一個請求

... 最後,希望有更多的資源可用於主線程來執行一些用戶啓動的計算。

這樣做意味着主循環必須等待,直到工人完全處理隊列,才能以正確的順序繪製所有內容,最終可能會導致使用過時工人的優勢。

這是我到目前爲止有:https://gist.github.com/automat/8566773(不WebGL的一部分,只是在消息隊列中,沒有主循環,因爲同步圖像framestep和等待工作是一個問題,也是)

順便說一下:通過紋理四邊形虛擬實例化幾何實體不是一種選擇。

你可以看看這裏的項目:https://github.com/automat/canvasGL.js(SRC/GL/cglContext.js應該是特別有趣)

這是什麼好?任何提示讚賞...

回答

1

我曾在圖形管道回來的日子裏,當你的平均聚合機是一套VME機架成本約$ 1,000.000,幾乎不能吐10K多晶硅50次/秒。接下來是我的頭頂上的一個非常粗略和粗略的概述,但是我已經編寫了使它工作的軟件,我很確定這種方式能夠以合理有效的方式完成工作。

基本上你在這裏需要的是一個很好的數據依賴性分析。

如果你想獲得一些計算能力,你有產卵儘可能多CPU內核儘可能工作線程。 Yur問題是一個簡單並行化的完美例子,因爲每個想要計算的幾何基元之間不存在依賴關係。

在這裏看來,你的主線程將沒有什麼可以做的,除了旋轉其虛擬拇指等待你的工人完成他的圈子咀嚼業務。您將避免阻止瀏覽器用戶界面,但在CPU功耗方面沒有任何收穫。

但是,你可以做的是:

  • 鴻溝你的圈子中成爲具有相當規模的數據包(假設100圈每人,在所有100圈的150包)。
    把所有這些數據包到一個共同的輸入隊列
  • 已經在你的CPU的每一個
  • 每個工作線程將選擇下一個可用的數據包從通用輸入隊列,並處理和運行相同的工作線程的實例將結果放回公共輸出隊列。
  • 讓主線程從輸出隊列中抓取數據包並將它們送入飢餓的GPU。

有了這種架構,您將可以讓所有CPU全速運行,在圈子上進行真正的並行計算。

通用隊列將充當簡單的自動負載平衡器。
想象一下,出於某種原因,某些圈子比其他圈子計算成本更高。已經得到緊急數據包的不幸的CPU將花費更多的時間處理它,而它的兄弟姐妹會將更快的數據包彈出隊列。
就像平均郵局的辦公桌上發生的工作負載平衡一樣,當幾個辦公桌服務於單一客戶隊列時。

一旦處理了第一批100個圓圈,從高級軟件到GPU的流水線就會開始填充。運行主應用程序的CPU可能花費很少的時間來提供GPU,並且工作線程幾乎可以將100%的CPU時間用作與在專用CPU上運行的同級運算器相同的計算。

總計算時間將幾乎除以系統中可用CPU的數量(在同步和其他背景噪聲中出現5%的損失)。

整個管道的全局同步需要一些思考,但基本上你知道給定幀生成多少數據包,所以你可以很容易地計算通過輸入和輸出隊列傳輸的數據包的數量,從而確定給定的圖像生成周期何時結束。儘管如此:這要假設你的圓包可以獨立計算,即它們僅依賴當前幀的全局信息(通常是相機位置和一些照明參數)。
如果你必須做全局遮擋剔除的事情,你可以吻你的並行處理再見(當然,除非你設計專門的並行算法)。

編輯:

我跑了一些基本的測試,看看工人們採取其它CPU的充分利用。請參閱this fiddle,其中9或10名工人正在緊密環行。

這是在FireFox上測試的,但由於使用blob創建工作代碼的安全限制而無法在IE11上運行。我只使用這個黑客爲了使演示適合JSFiddle。如果您使用常規的.js文件,我想代碼應該在IE11上運行良好。

<script id='worker' type='worker'> 
onmessage = function (e) 
{ 
    // eat 100% CPU for the requested number of seconds 
    var done = Date.now()+e.data*1000; 
    while (Date.now() < done) { /* wasting CPU here */ } 

    // signal done 
    postMessage(''); 
}; 
</script> 

由於某些原因,CPUS似乎並未完全佔用。這可能與我的虛擬等待循環有關,或者可能是未充分利用多核的工作人員分配。
根據我從Mozilla文檔中瞭解到的情況,工作人員應該在多個內核上生成,但據我所知,您無法控制這些內核。

無論如何,這可能是一些性能測試的基礎,如果你使用真正的計算而不是假的。當然,您應該使用直接數據訪問,否則郵件副本將破壞工作人員之間共享數據的好處。

+0

這並不完全正確。將工作推送給工作人員可以保持主頁的響應。如果計算一些幾何圖形需要500到10000毫秒,如果您在主頁上執行此操作,除非您編寫一些漸進式事件驅動的生成器,則網頁會凍結500到10000毫秒。用戶無法做任何事情。另一方面,如果您將該工作推送給工作人員,該頁面可以繼續響應用戶輸入。它甚至不管是否有2個CPU,因爲工作人員是線程,這仍然意味着您的主頁面將有機會響應用戶輸入。 – gman

+0

@gman ???用戶界面與這一切有什麼關係?顯然,CPU密集型工作將在其他線程中完成,無論如何。用戶界面線程唯一需要做的就是控制整個計算鏈:啓動/停止並傳遞用戶輸入(攝像機移動,播放器位移等)。 –

+0

我們在說WebGL,所以我們在瀏覽器中。讓我們呆在那裏是半徑的屏幕上的滑塊。如果需要10000毫秒(10秒)來產生一個球體,那麼在整個10秒內滑塊變得無響應。另一方面,如果在工作人員上計算球體,則滑塊保持響應。它可能是10秒,直到一個球體出現正確的大小,至少該滑塊沒有被卡住10秒。用戶還可以更新其他內容,文本字段,其他滑塊等。但是,只有在幾何體是在工作人員中計算或分解爲小事件的情況下才可以。 – gman