是否可以使用WebGL在浏览器中在GPU上运行折叠操作?

时间:2014-01-23 14:50:27

标签: javascript browser webgl gpu

我正在运行几乎所有的数据处理应用程序:

var f = function(a,b){ /* any function of type int -> int -> int */ };
var g = function(a){ /* any function of type int -> int */ };
function my_computation(state){
    var data = state[2];
    for (var i=0,l=data.length,res=0; i<l; ++i)
        res = f(res,g(data[i]));
    state[3] = res;
    return res;
}

这种模式几乎是foldl的模式。这个计算在CPU上不够快。是否有可能在浏览器上以某种方式在GPU上运行该计算?

3 个答案:

答案 0 :(得分:3)

来自你的评论:

  

我对顶点着色器了解不多,但据我所知,它在孤立的像素中工作,而对于折叠,你需要一个累积模式。否?

如果要使用WebGL对数组进行计算,则很可能希望在片段着色器中进行,而不是使用顶点着色器。如果使用覆盖整个视口的输入几何体,则片段着色器就是一个逐个像素地计算图像的程序。它可以用作输入数字参数和任意纹理。此外,您可以将输出渲染为纹理。

这是您输入的方式:将输入数据存储在纹理中,并让片段着色器在纹理中进行查找。在纹理中进行多次偏移查找是完全正常的。例如,这就是模糊效果的工作原理。

你很关心积累。没有本地方法可以对所有像素进行折叠。但是,如果您可以以“map-reduce”方式表达算法,其中reduce操作组合了两个输出,而不关心它们是否是先前reduce步骤的输入,那么您可以这样做:< / p>

  1. 将输入数据加载到1像素高的N像素宽纹理中。 (不确定使用方形纹理是否可以提供更好的上限,但这更容易描述。)
  2. 运行您的“地图”(g,非累积计算)着色器程序,生成中间输出纹理。
  3. 运行一个着色器,在中间纹理的每个对相邻像素(或类似物)上执行“减少”操作(f),生成另一个纹理的一半宽。 / LI>
  4. 在输出上再次做同样的事情。
  5. 这将只在O(log n)JavaScript操作中为您提供单一答案。

答案 1 :(得分:1)

我会说是的。我自己经常这样做。您的数据将作为顶点属性缓冲区附加,自定义着色器将执行折叠代码,将结果“渲染”到屏幕外缓冲区。然后,您将结果缓冲区读回CPU内存。

答案 2 :(得分:1)

鉴于您希望在浏览器上运行它,您受到WebGL /扩展支持的限制,特别是对CPU数据的CPU访问。

您可以在下面的代码库中查看用于过滤器/边缘检测的着色器代码,以了解如何在fragment shader中执行此操作。

https://github.com/prabindh/sgxperf/blob/master/sgxperf_strings.cpp

在此之后,您可以使用readPixels访问数据。注 - 片段着色器只能输出定点数据。