一、什么是Javascript实现GPU加速?

CPU与GPU设计目标不同,导致它们之间内部结构差异很大。
CPU需要应对通用场景,内部结构非常复杂。
而GPU往往面向数据类型统一,且相互无依赖的计算。
所以,我们在Web上实现3D场景时,通常使用WebGL利用GPU运算(大量顶点)。
但是,如果只是通用的计算场景呢?比如处理图片中大量像素信息,我们有办法使用GPU资源吗?这正是本文要讲的,GPU通用计算,简称GPGPU。

二、实例演示:色块识别。

如下图所示,我们识别图片中彩虹糖色块,给糖果添加表情。

 

2.1、实例地址(打开页面后,依次点击按钮“使用CPU计算”、“使用GPU计算”):
http://tgideas.qq.com/2018/brucewan/gpgpu.html

2.2、运行代码:

  1. var rgb2hsv = function(r, g, b) {
  2. var max = Math.max(r, g, b), min = Math.min(r, g, b),
  3. d = max - min,
  4. h,
  5. s = (max === 0 ? 0 : d / max),
  6. v = max / 255;
  7. switch (max) {
  8. case min: h = 0; break;
  9. case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
  10. case g: h = (b - r) + d * 2; h /= 6 * d; break;
  11. case b: h = (r - g) + d * 4; h /= 6 * d; break;
  12. }
  13. return {
  14. h: self.hueIndexs[parseInt(h*360)],
  15. s: s,
  16. v: v
  17. }
  18. };

运行次数:262144次

2.3、测试结论:
实例中,我们分别使用GPU和CPU进行色相转换(防止光线影响识别准确度),其余步骤均一致。

测试平台 测试结论
PC GPU较CPU优势较少
iOS GPU较CPU优势较少
Android vivoX20(运行10次平均)
CPU:770ms,GPU:270
GPU较CPU快2.85倍
三星S7(运行10次平均)
CPU:982ms,GPU:174ms
GPU较CPU快5.64倍

2.4、使用GPGPU意义:
GPU与CPU数据传输过程,与GPU实际运算耗时相当,所以使用GPU运算传输成本过高,实测在Android中具有较大优势。
本测试案例是从webAR项目中抽取,需要实时跟踪用户摄像头处理视频流(256*256),使用GPU计算意义非常大,否则无法实现实时跟踪。

三、如何实现GPU通用计算?

3.1、首先,我们通过一张流程图,演示原理:

3.2、实现:

3.2.1、创建顶点着色器,只是传递了贴图坐标。

  1. attribute vec4 position;
  2. varying vec2 vCoord;
  3. void main() {
  4. vCoord = position.xy * 0.5 + 0.5;
  5. gl_Position = position;
  6. }

3.2.2、创建片元着色器,根据贴图坐标贴图。

  1. precision highp float;
  2. varying vec2 vCoord;
  3. uniform sampler2D map;
  4. void main(void) {
  5. vec4 color = texture2D(map, vCoord);
  6. gl_FragColor = color;
  7. }

3.3.3、根据如上着色器代码,创建程序对象,变量code是我们要传入的用于计算的代码。

  1. // 绑定并编译着色器程序
  2. var vertexShaderSource = '...';
  3. var fragmentShaderSource = '...' + code + '...';
  4. var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  5. gl.shaderSource(vertexShader, vertexShaderSource);
  6. gl.compileShader(vertexShader);
  7. var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  8. gl.shaderSource(fragmentShader, fragmentShaderSource);
  9. gl.compileShader(fragmentShader);
  10.  
  11. // 创建程序对象
  12. var program = gl.createProgram();
  13. gl.attachShader(program, vertexShader);
  14. gl.attachShader(program, fragmentShader);
  15. gl.linkProgram(program);
  16. gl.useProgram(program);

3.3.4、传入顶点数据,创建一个面覆盖整个画布。

  1. // 顶点数据传输
  2. var vertices = new Float32Array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0]);
  3. var vertexBuffer = gl.createBuffer();
  4. gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  5. gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  6. var aPosition = gl.getAttribLocation(program, 'position');
  7. gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
  8. gl.enableVertexAttribArray(aPosition);

3.3.5、传入原始数据,本例中传入我要处理的图像数据,作为贴图,最终绘制到屏幕。

  1. var gl = this.gl;
  2. var program = this.program;
  3. var texture = gl.createTexture();
  4. var uMap = gl.getUniformLocation(program, 'map');
  5.  
  6. gl.activeTexture(gl.TEXTURE0);
  7. gl.bindTexture(gl.TEXTURE_2D, texture);
  8.  
  9. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
  10. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  11. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  12. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  13. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  14. gl.generateMipmap(gl.TEXTURE_2D);
  15.  
  16. gl.uniform1i(uMap, 0);
  17.  
  18. // 绘制
  19. gl.clearColor(0, 0, 0, 1);
  20. gl.clear(gl.COLOR_BUFFER_BIT);
  21. gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

3.3.6、从最终绘制的画面上,获取颜色信息作为最终处理结果数据。

  1. var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
  2. gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

3.3.7、完整代码:
http://tgideas.qq.com/2018/brucewan/gpu.js

其实清楚原理后,整体实现比较简单。
但是对于不了解WebGL的同学来说,理解上有一定难度,我后续准备写一个系列的WebGL教程,有兴趣的同学可以关注。

四、有无现成类库?

大家可以看到,我实现的gpu.js中,并没有将javascript转换成着色器语言(类C),而是用户直接传入着色器代码。但是github上已有将javascript转换为着色器语言的库。
https://github.com/gpujs/gpu.js

为什么我没有直接使用呢?
1、简单的使用,2k可以实现的代码,不想引入200k的库;
2、数据输入输出可以由自己灵活控制;
3、着色器语言很简单,特别只是使用基础运算逻辑的代码,没必要由库从Javascript转换。

没有WebGL基础的同学,建议直接使用https://github.com/gpujs/gpu.js,从本文理解整体逻辑;
有一定基础的同学,建议由http://tgideas.qq.com/2018/brucewan/gpu.js自己定制,更为灵活。
另外,这个组件我没打算深度封装,也没打算维护……嗯,就这样。

Javascript如何实现GPU加速?的更多相关文章

  1. 开启gpu加速的高性能移动端相框组件!

    通过设置新的css3新属性translateX来代替传统的绝对定位改变left值的动画原理,新属性translateX会开启浏览器自带的gpu硬件加速动画性能,提高流畅度从而提高用户体验, 代码有很详 ...

  2. CSS动画的性能分析和浏览器GPU加速

    此文已由作者袁申授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 有数的数据大屏可以在一块屏幕上展示若干张不同的图表,以炫酷的方式展示各种业务数据.其中有些图表使用CSS实现了 ...

  3. Theano在windows下的安装及GPU加速

    安装环境:wondows 64bit Teano安装测试 1. Anaconda 安装 Anaconda是一个科学计算环境,自带的包管理器conda很强大.之所以选择它是因为它内置了python,以及 ...

  4. GPU 加速NLP任务(Theano+CUDA)

    之前学习了CNN的相关知识,提到Yoon Kim(2014)的论文,利用CNN进行文本分类,虽然该CNN网络结构简单效果可观,但论文没有给出具体训练时间,这便值得进一步探讨. Yoon Kim代码:h ...

  5. ubuntu 15 安装cuda,开启GPU加速

    1 首先要开启GPU加速就要安装cuda.安装cuda,首先要安装英伟达的驱动.ubuntu有自带的开源驱动,首先要禁用nouveau.这儿要注意,虚拟机不能安装ubuntu驱动.VMWare下显卡只 ...

  6. Silverlight - GPU加速

    1. 在Silverlight plug-in上设置 <param name="enableGPUAcceleration" value="true" / ...

  7. 用cudamat做矩阵运算的GPU加速

    1. cudamat简介 cudamat是一个python语言下,利用NVIDIA的cuda sdk 进行矩阵运算加速的库.对于不熟悉cuda编程的程序员来说,这是一个非常方便的GPU加速方案.很多工 ...

  8. 深度学习“引擎”之争:GPU加速还是专属神经网络芯片?

    深度学习“引擎”之争:GPU加速还是专属神经网络芯片? 深度学习(Deep Learning)在这两年风靡全球,大数据和高性能计算平台的推动作用功不可没,可谓深度学习的“燃料”和“引擎”,GPU则是引 ...

  9. GPU加速有坑?

    大多数人都知道有动画的地方可以使用GPU来加速页面渲染. 例如,做优化的时候,将使用left和top属性的动画修改成使用transform属性的CSS动画.或者听到别人教你使用transform:tr ...

随机推荐

  1. python的函数(三)

    1,函数多类型传值和冗余参数 2,递归函数 1,函数多类型传值和冗余参数 1.0,函数多类型传值 定义1个函数, def fun(x,y): return x+y 调用该函数print fun(1,2 ...

  2. python的函数(一)

    摘要: python的函数(一)主要写函数的基础部分. 1,函数的好处 2,函数的定义与调用 1,函数的好处 函数应该有2个好处: 1,是降低代码的复杂度, 2,是减少代码量,避免重复的写相同的代码. ...

  3. MariaDB实现主从配置及读写分离(一)

    一.主从复制方案 1.  在两台CentOS7虚拟机上分别部署MariaDB, 主数据库服务器IP为192.168.17.235, 从服务器IP为192.168.17.238. 从服务器通过调取主服务 ...

  4. 运维利器万能的 strace

    strace是什么? 按照strace官网的描述, strace是一个可用于诊断.调试和教学的Linux用户空间跟踪器.我们用它来监控用户空间进程和内核的交互,比如系统调用.信号传递.进程状态变更等. ...

  5. pycharm的放大和缩小字体的显示 和ubunt的截圖工具使用 ubuntu上安装qq微信等工具

    https://www.cnblogs.com/sui776265233/p/9322074.html#_label0 ubuntu: 截圖工具的使用 在ubuntu 10.04 的时候,还可以很方便 ...

  6. npm安装vue

    目录 npm安装vue Vue.js 是什么 直接用script引入 安装vue 对不同构建版本的解释 安装命令行工具 (CLI) 安装cnpm 安装vue-cli 新建vue项目 运行服务 目录结构 ...

  7. windows10下安装source insight 4.0(破解版)

    1.从官网下载source insight4.0版本(不用下载,在后面已经把所有需要的文件都准备好了); 2.安装source insightt4.0; 3.使用下载好的sourceinsight4. ...

  8. python使用mechanize模拟登陆新浪邮箱

    mechanize相关知识准备: mechanize.Browser()<br># 设置是否处理HTML http-equiv标头 set_handle_equiv(True)<br ...

  9. Github的一般用法

    写了这么多年代码,源代码版本管理从一开始的没有后来的VSS,CVS,到现在一直在使用的SVN,但这些都是集中式的版本管理. 而分布式的版本管理还没有使用过. 今天看了看Github,研究一下怎么使用G ...

  10. java使用elasticsearch分组进行聚合查询(group by)-项目中实际应用

    java连接elasticsearch 进行聚合查询进行相应操作 一:对单个字段进行分组求和 1.表结构图片: 根据任务id分组,分别统计出每个任务id下有多少个文字标题 .SQL:select id ...