
在我的之前的測評中,我利用Termux和Aid Learning測試過基于C/C++的openmp并行程序,基于Java的并行程序,還有基于MPI以及基于Java的分布式集群并行。但是很遺憾,一直無法成功開發基于OpenCL的GPU并行編程。
這是主要是因為Android并沒有采用glibc作為C庫,而是采用了Google自己開發的Bionic Libc,它的官方Toolchain也是基于Bionic Libc而并非glibc的。因此我使用Termux和Aid Learning里的libopencl.so是無法調用OpenCL的。
與glibc相比,Bionic Libc有如下一些特點:
- 采用BSD License,而不是glibc的GPL License;
- 大小只有大約200k,比glibc差不多小一半,且比glibc更快;
- 實現了一個更小、更快的pthread;
- 提供了一些Android所需要的重要函數,如“getprop”, “LOGI”等;
- 不完全支持POSIX標準,比如C++ exceptions,wide chars等;
- 不提供libthread_db 和 libm的實現
目前我還沒有找到正確的方式在Termux和Aid Learning中調用手機OpenCL來進行GPU并行計算(如果您能解決,麻煩您教教我!)。
那么Termux和Aid Learning就沒法用GPU加速計算了嗎?“只要思想不滑坡,辦法總比困難多”!針對Termux和Aid Learning的自身特點考慮解決方案唄!
手機軟件Termux和Aid Learning是一個安卓上模擬的Linux環境,并非真正的Linux,也不是安卓的那個Linux,比如,他們就無法直接開發傳統的Linux桌面程序,也不能開發安卓桌面程序。但是當前基于Web的技術可以解決這個問題,而JavaScript是Web開發的主流語言。Node.js等先進工具都能用啊!然后WebGL不就能上了嗎?
比如這樣的,WebGL開發的三維地球就可以用在Termux或者Aid Learning。

詳情見:
myastrotong:Python爬取肺炎疫情數據并開發三維疫情數字地球?zhuanlan.zhihu.com
再進一步,GPU.js是不是也能用上了!這不就能夠調用安卓的GPU了!JS完美的解決了我的需求!
可能大家對JavaScript的計算性能有質疑,畢竟這是一門腳本語言。說他性能拼得過C/C++,打死也沒人信。
有大神早就做過相關測試了,各語言計算性能對比測試見這里:
Javascript,C++,C#,Java,Lua,Python,Ruby,F#語言渲染性能評測 | AlloyTeam?www.alloyteam.com
結果在這兒:


這個測試是2010年左右的作品了,其中使用的還是32位的vs2008,Java還是jdk1.6。
大家都知道改為64位以后,c++的計算速度還能進一步提高。Java的性能經過這些年發展也有一定提高。但是更需要指出來的是,Javascript、Python這類腳本語言的速度提升得更快!所以該測試還是非常有指導意義的。
在這個測試中,JS的Chrome V8引擎成為了計算效率最高的腳本語言引擎。所以可以看出來,加入JIT的加持使得Chrome V8引擎輔助Javascript一躍從前端跑進了后端。厲害。
那么JavaScript語言內部還有很多引擎啊,各個引擎之間的性能對比如何呢?
QuickJS的作者,大牛Fabrice Bellard,同時還是Qemu、FFmpeg的作者,測試了如下各個Javascript Engine的性能!結果如下表所示:
具體解釋見網站:
QuickJS Benchmark?bellard.org
可以看到,加入JIT的V8引擎性能獨領風騷,基本上是取得了碾壓式的勝利。
沒了JIT的其他引擎,大家的性能也就差不多了,基本上就是那些腳本引擎該有的樣子,搓唄!
自帶V8引擎的Node.js在Termux和Aid Learning都能夠安裝(Node.js不是一門語言也不是一個框架,它是基于Chrome V8引擎的JavaScript運行時環境),此外在手機的大多數瀏覽器內都是自帶V8的。這就酸爽了。腳本語言,性能還這么好,寫起程序來那個順暢,還能輕松的開發跨平臺應用(比如electron開發的vscode)!溜啊!
當然QuickJS自身也是一個神器,無論怎么贊美它都不過分,搞嵌入式JS開發美得很,以后再作介紹,在此不予贅述。Bellard那是大神,給咱們引入了另一個世界,回頭再表!
JavaScript里面有一個WebGL技術,可以在網頁調用OpenGL技術,這不就是我想要的!
我在網頁端調用能否調用OpenCL、CUDA呢?答案當然是否!但是有一個新技術:GPU.js。用這個就可以在網頁端調用GPU來進行并行計算了!
GPU.js - GPU accelerated Javascript?gpu.rocks
這個技術就可以完全避免Termux和Aid learning無法調用安卓libopencl.so的尷尬!
改進官網的矩陣乘法的例子,在小米Mix2s上分別測試在GPU、CPU上128、256、512、1024維矩陣乘法。
分別在小米瀏覽器、UC瀏覽器、FireForx、Chrome四款瀏覽器上進行測試。
下圖各數據的意義是:
第一行表示矩陣維數;
第二行表示CPU計算時間(毫秒);
第三行表示GPU并行計算時間(毫秒);
第四行表示加速比。
測試1:

測試2:

測試3:

測試4:

值得指出的是,以上數據只是某次計算的結果,每一次計算可能求得結果其實并不一樣,有時候差距還挺大。但是數量級基本是沒錯的。
由計算結果可見:
隨著矩陣維數增加,GPU的計算性能要遠優于CPU的計算性能,在1024維矩陣的計算上輕松提升了60~80倍。無論在那個瀏覽器上,在復雜大矩陣計算上,GPU的并行計算性能都取得了碾壓式的勝利!
FireFox瀏覽器上的GPU計算效率是最高的。
Chrome瀏覽器上CPU的計算效率更好。
通過上述處理,安卓手機配合Termux和Aid Learning獲得了強大的算力,這個算力是遠超過樹莓派4B了。大家現在可以嘗試Tersorflow.js之類了,看看能不能搞出更有創意的玩法。
算例的源碼
新建一個index.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title><script src="dist/gpu-browser.min.js"></script><script>
window.onload = function(){
const gpu = new GPU();const multiplyMatrix = gpu.createKernel(function(a, b) {let sum = 0;for (let i = 0; i < 128; i++) {sum += a[this.thread.y][i] * b[i][this.thread.x];}return sum;
}).setOutput([128, 128]);function multiplyMatrixByCPU(A, B) {let tempMatrix = new Array( 128); for(let i=0;i<128;i++){tempMatrix [i]=new Array(128);for(let j=0;j<128;j++){tempMatrix[i][j]=0;for(let n =0;n<128;n++){tempMatrix[i][j]+=A[i][n]*B[n][j];}}}return tempMatrix;
} var a=new Array( 128);
var b=new Array( 128);
for(var i=0;i<128;i++){a[i]=new Array(128);b[i]=new Array(128);for(var j=0;j<128;j++){a[i][j]=j*0.01;b[i][j]=j*0.21;}
}var start = window.performance.now();
const d = multiplyMatrixByCPU(a, b);
var end = window.performance.now();var start2 = window.performance.now();
const c = multiplyMatrix(a, b);
var end2 = window.performance.now();var duration = end - start;
var duration2 = end2 - start2;var two = document.getElementById("two");
two.innerHTML =duration;var three= document.getElementById("three");
three.innerHTML= duration2 ;var matSize= document.getElementById("matSize");
matSize.innerHTML= 128;var ratio= document.getElementById("ratio");
ratio.innerHTML= duration2/duration;}
</script>
</head><body><p>Matrix size:<span id="matSize"></span></p><p>global CPU:<span id="two"></span></p><p>global GPU:<span id="three"></span></p><p>GPU vs CPU:<span id="ratio"></span></p>
</body>
</html>
你需要的是在index.html目錄下新建一個文件夾dist,然后上官網下載gpu-browser.min.js文件放到dist文件夾下。
然后在index.html所在文件夾下開啟http-server:
python3 -m http.server 9999
或者:
npm start -- -p 9999
然后在手機瀏覽器輸入
http://localhost:9999/index.html