[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] WebKit 20-50% slower than Chrome/Minefield using large Float32Array Arrays



If there was ever a job for the GPU, this is it!

I've done this kind of thermal simulation in the GPU in the past - and
the results were pretty good.  (I used to do simulation of thermal
imaging in military IR cameras - and we needed to simulate the thermal
consequences of an explosion).

Make the grid into a texture map - write a shader that takes the last
iteration's raw data as a texture map and generates one cell of the
output from it...that would require porting your thermal calculations
into GLSL - but I'd be surprised if that was hard.   Then you can
compute the entire update by drawing a single quadrilateral to a second
texture/FBO.   If the calculation part is really complex, you might need
to break it into several stages and do each one in a separate rendering
pass...but it's hard to imagine that this would be difficult.

If you need to do it in 3D then pass a number of adjacent 2D slices as
textures into a shader that computes a 2D slice as output...you then
draw one 2D slice with each quadrilateral you draw - but you can do all
of that in a single draw call.

When you have the calculated result, you can do the false-color
rendering of the resulting raw data with a second shader that uses a 1D
texture map to convert temperature to color.

The trick is to make sure that the data never leaves the GPU - do all of
your storage with textures/FBO's and all of your calculations and
display in GLSL.

Because the S-L-O-W JavaScript code is now running as a GLSL program in
the mind-blowingly fast GPU, I bet you could get the raw frame rate for
a 3D case up to maybe a hundred hertz...much faster than you can display
it.   This enables you to use much smaller time-steps - which reduces
the velocities and that drastically improves the parts of the
calculation that tend towards numerical instability (advection was the
worst culprit IIRC).

  -- Steve


On 02/17/2011 04:23 AM, Thatcher Ulrich wrote:
> Cool demo.
>
> One thing you should try, without even going to WebGL, is filling the
> canvas using context.putImageData() instead of lots of fillRect calls.
>  Perhaps also best to render into a 100x100 canvas, and have the
> browser scale it onto the correct size on the page, instead of doing
> that in your paint routine.  Though I think the scaling will be smooth
> instead of blocky; not sure if you want that.
>
> The other thing you should definitely do is make a color table instead
> of making and parsing "hsl(...)" strings for every pixel.
>
> Code (untested, edited from yours) would look something like:
>
> model2d.displayTemperature = function(canvas, model) {
>     var ctx = canvas.getContext('2d');
>     ctx.fillStyle = "rgb(0,0,0)";
>     ctx.globalCompositeOperation = "destination-atop";
>
>     // Set the CSS width/height to the desired display height.
>     // Better to just do this in the HTML on the page using the
>     // style attribute.
>     canvas.style.width = canvas.clientWidth + 'px';
>     canvas.style.height = canvas.clientHeight + 'px';
>
>     // Force the actual source pixel data to be 100x100.
>     canvas.width = 100;
>     canvas.height = 100;
>
>     var hue;
>     var rgb;
>
>     var columns = model.nx;
>     var rows = model.ny;
>     var ycols, ycols_plus_x;
>
>     var t = model.t;
>     var min = model2d.getMinTypedArray(t);
>     var max = model2d.getMaxTypedArray(t);
>     var scale = 255/(max - min);
>     var temp;
>     var imdata = ctx.getImageData(0, 0, 100, 100);
>     var data = imdata.data;
>     for (y = 0; y < rows; y++) {
>         ycols = y * rows;
>         var pix_index = y * 100;
>         for (x = 0; x < columns; x++) {
>             ycols_plus_x = ycols + x;
>             temp = model.t[ycols_plus_x];
>             hue =  Math.abs(Math.round(scale * temp - min) - 255);
>             // Assume a pre-computed color table!
>             rgb = color_table[Math.min(Math.floor(hue + 0.5), 255)];
>             data[pix_index] = rgb.r;
>             data[pix_index + 1] = rgb.g;
>             data[pix_index + 2] = rgb.b;
>             data[pix_index + 3] = rgb.a;
>             pix_index += 4;
>         }
>     }
>     ctx.putImageData(imdata, 0, 0);
> }
>
> -T
>
> On Thu, Feb 17, 2011 at 6:42 AM, Stephen Bannasch
> <stephen.bannasch@deanbrook.org> wrote:
>   
>> Here's a test using large Float32Array Typed Arrays (many sized 100x100)
>> where WebKit ends up 20-50% slower than Chrome and Minefield. In these tests
>> Minefield edges out Chrome but not by much.
>>
>> I found that 90% of the time was spent rendering the false-color thermal map
>> graphics.
>>
>> Suggestions for how to speed this up would be great.
>>
>> I created an initial port of our Java Energy2D application running in
>> JavaScript. The backing model is doing a thermal simulation of conductivity,
>> convection, and radiation with 10,000 cells.
>>
>>  http://visual-demos.dev.concord.org/seasons/earth/model2d.html
>>
>> The JavaScript implementation uses JavaScript Typed Arrays so it only works
>> with browsers that supports WebGL (Chrome 9, recent FireFox betas, and
>> WebKit nightlies).
>>
>> The original Java version of Energy2D can be seen here:
>> http://energy.concord.org/energy2d/index.html
>>
>> The JavaScript simulation model starts with a fixed high-temperature spot in
>> the middle.
>>
>> The basic model simulation space is a 100x100 grid, 10,000 cells the same as
>> the Java version of Energy2D.
>>
>> The JavaScript code is here:
>> https://github.com/stepheneb/seasons/blob/master/earth/model2d.js
>>
>> I'm getting about 4 model iterations/s on Chrome and FF betas, and about 3
>> on WebKit/Safari.
>>
>> I wondered how much of the time was doing graphics and how much was running
>> the model ... turns out a huge bottleneck is rendering the graphics.
>>
>> The demo page renders the false-color thermal map with one of two
>> techniques: using HTML5 Canvas, or stuffing 10,000 styled divs using
>> innerHTML. I was surprised when the two methods ended up practically
>> equivalent in time.
>>
>> I'd like to find a much quicker way to render the graphics ... perhaps using
>> WebGL.
>>
>> I'm very impressed at how fast the model calculation runs.
>>
>> My tests below run the model for 15s on my MacOS X 10.6.6 PowerBook Pro with
>> a 2.66 GHz Intel Core i7.
>>
>>
>> Rendering to both the canvas visualization and the table of data:
>>
>> Browser                            model steps      model steps/s
>> --------------------------------------------------------------------
>> Chrome v9.0.597.102                  59              3.9
>> Minefield 4.0b12pre (2011-02-16)     60              4.0
>> WebKit v5.0.3 (6533.19.4, r78685)    48              3.2
>>
>>
>> Rendering just to the canvas visualization:
>>
>> Browser                            model steps      model steps/s
>> --------------------------------------------------------------------
>> Chrome v9.0.597.102                  68              4.5
>> Minefield 4.0b12pre (2011-02-16)     84              5.6
>> WebKit v5.0.3 (6533.19.4, r78685)    64              4.3
>>
>>
>> With rendering to the canvas and the table of data disabled:
>>
>> Browser                            model steps      model steps/s
>> --------------------------------------------------------------------
>> Chrome v9.0.597.102                 489             32.6
>> Minefield 4.0b12pre (2011-02-16)    507             33.8
>> WebKit v5.0.3 (6533.19.4, r78685)   220             14.7
>>
>> What is speeding this up is the use of JavaScript Typed Arrays:
>>
>>  http://www.khronos.org/registry/typedarray/specs/latest/
>>
>> This capability is associated with browsers that have implemented WebGL but
>> none of the JavaScript Energy2D code is actually running on the GPU. The
>> speedup is because of optimizations the JavaScript engines can make with
>> math when working with fixed length arrays and one kind of number.
>>
>>
>> -----------------------------------------------------------
>> You are currently subscribed to public_webgl@khronos.org.
>> To unsubscribe, send an email to majordomo@khronos.org with
>> the following command in the body of your email:
>> unsubscribe public_webgl
>> -----------------------------------------------------------
>>
>>
>>     
> -----------------------------------------------------------
> You are currently subscribed to public_webgl@khronos.org.
> To unsubscribe, send an email to majordomo@khronos.org with
> the following command in the body of your email:
> unsubscribe public_webgl
> -----------------------------------------------------------
>
>   

-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl
-----------------------------------------------------------