Simulations on GPU. Introduction

Super-computer in your home PC

Modern video cards with hundreds of shaders have performance of the order of 1TFlops. Access to the main GPU memory takes hundreds of cycles and can slow down calculations. But if you have a task in which thousands of independent similar threads start at the same time, then while some of them are waiting for memory other can be calculated. Therefore your GPU may be 100 times faster than CPU.

WebGL and fractal generation on GPU


We can use "graphical" GLSL shaders to generate fractals on GPU. The fragment shader below calculates color for the pixel with coordinates vec2 gl_FragCoord (see e.g. The Mandelbrot and Julia sets Anatomy)
<script id="shader-fs" type="x-shader/x-fragment"> 
#ifdef GL_ES
precision highp float;
#endif
  uniform vec2 scale;
  const vec2 c = vec2(.259, .001);
void main(void) {
   float R = (gl_FragCoord.x - scale.x) / scale.y;
   float I = (gl_FragCoord.y - scale.x) / scale.y;
   float R2 = R*R, I2 = I*I;
   int mm;
   for(int m = 0; m < 255; m++){
     I=(R+R)*I + c.y;  R=R2-I2 + c.x;  R2=R*R;  I2=I*I;   mm = m;
     if( R2 + I2 > 4. ) break;
   }
   if (mm == 254) gl_FragColor = vec4(0., 0., 0., 1.);
   else{
    float a = float(mm);  a = mod(a, 60.) / 20.;
    gl_FragColor = vec4( max(0., abs(a - 1.5) - .5),
      max(0., 1. - abs(a - 1.)), max(0., 1. - abs(a - 2.)), 1.);
   }
}
</script> 
We prepare the vertex shader
<script id="shader-vs" type="x-shader/x-vertex"> 
  attribute vec2 vPos;
void main(void) {
   gl_Position = vec4(vPos, 0., 1.);
}
</script> 
and "draw" the 2×2 square (which fills the whole viewport)
   var posAtrLoc = gl.getAttribLocation(prog, "vPos");
   gl.enableVertexAttribArray( posAtrLoc );
   gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
   var vertices = new Float32Array([-1,-1, 1,-1, 1,1, -1,1]);
   gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
   gl.vertexAttribPointer(posAtrLoc, 2, gl.FLOAT, false, 0, 0);
   var size = canvas.width;
   gl.uniform2f( gl.getUniformLocation(prog,"scale"), size/2, size/2.5 );

   gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
Then WebGL executes the fragment shader for every pixel. By the way I can get up to 8000×8000 fractal picture (with the corresponding canvas size) and save it as image in Firefox.

WebGL extensions and shader validation

It is impossible to make Deep zoom into the Mandelbrot set with the Float32 numbers. Therefore even in this simple application we need Float64 extension. (Fortunately Julia sets and waves animations are funny with Float32 :)

WebGL (based on OpenGL ES) is made to support mobile devices with limited resources. To use more powerful OpenGL 3+ drivers on a desktop you need to switch off ANGLE and shader validation. You can make one more "experimental" shortcut to Chrome with the --disable-glsl-translator --use-gl=desktop keys (they say that for security reasons it is better to use shader validation).

OES_texture_float and Vertex_texture2D extensions are implemented in Chrome and Firefox. The WebGL implementation may optionally accept a texture with pixel type FLOAT as the color attachment to an FBO. Applications must check such an FBO for completeness after attempting to make this attachment, e.g.

   var err = "Your browser does not support ";
   try { ext = gl.getExtension("OES_texture_float");
   } catch(e) {}
   if ( !ext ) {alert(err + "OES_texture_float extension"); return;}
   ...
   texture = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, texture);
   gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, n,n,0, gl.RGBA, gl.FLOAT, pixels);
   FBO = gl.createFramebuffer();
   gl.bindFramebuffer(gl.FRAMEBUFFER, FBO);
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
     gl.TEXTURE_2D, texture, 0);
   if( gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
     alert(err + "FLOAT as the color attachment to an FBO");

WebCL and cloud computing

WebGL allows us to write simple shaders for GPU but to simulate Nature we need more flexibility. They are adding extensions step by step but WebCL = Web + OpenCL will be a huge jump to the cloud computing. Your mobile device will be able to send a task (shaders) to a remote "cloud server" and get back result (e.g. ray-traced, HD picture for a web-based game) in real time. See WebCL examples.
Simulations on GPU
updated   2 June 2011