在我的之前的测评中,我利用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#语言渲染性能评测 | AlloyTeamwww.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 Benchmarkbellard.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 Javascriptgpu.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