RiverTrail - JavaScript GPPGU Data Parallelism

Posted by JoshReuben on Geeks with Blogs See other posts from Geeks with Blogs or by JoshReuben
Published on Thu, 29 Nov 2012 07:02:51 GMT Indexed on 2012/11/29 11:07 UTC
Read the original article Hit count: 313

Filed under:

 

Where is WebCL ?

The Khronos WebCL working group is working on a JavaScript binding to the OpenCL standard so that HTML 5 compliant browsers can host GPGPU web apps – e.g. for image processing or physics for WebGL games - http://www.khronos.org/webcl/ . While Nokia & Samsung have some protype WebCL APIs, Intel has one-upped them with a higher level of abstraction: RiverTrail.

Intro to RiverTrail

Intel Labs JavaScript RiverTrail provides GPU accelerated SIMD data-parallelism in web applications via a familiar JavaScript programming paradigm. It extends JavaScript with simple deterministic data-parallel constructs that are translated at runtime into a low-level hardware abstraction layer. With its high-level JS API, programmers do not have to learn a new language or explicitly manage threads, orchestrate shared data synchronization or scheduling. It has been proposed as a draft specification to ECMA a (known as ECMA strawman).

RiverTrail runs in all popular browsers (except I.E. of course).

To get started, download a prebuilt version https://github.com/downloads/RiverTrail/RiverTrail/rivertrail-0.17.xpi , install Intel's OpenCL SDK http://www.intel.com/go/opencl and try out the interactive River Trail shell http://rivertrail.github.com/interactive

For a video overview, see  http://www.youtube.com/watch?v=jueg6zB5XaM .

ParallelArray

the ParallelArray type is the central component of this API & is a JS object that contains ordered collections of scalars – i.e. multidimensional uniform arrays. A shape property describes the dimensionality and size– e.g. a 2D RGBA image will have shape [height, width, 4]. ParallelArrays are immutable & fluent – they are manipulated by invoking methods on them which produce new ParallelArray objects. ParallelArray supports several constructors over arrays, functions & even the canvas.

// Create an empty Parallel Array

var pa = new ParallelArray();

// pa0 = <>

 

// Create a ParallelArray out of a nested JS array.

// Note that the inner arrays are also ParallelArrays

var pa = new ParallelArray([ [0,1], [2,3], [4,5] ]);

// pa1 = <<0,1>, <2,3>, <4.5>>

 

// Create a two-dimensional ParallelArray with shape [3, 2] using the comprehension constructor

var pa = new ParallelArray([3, 2], function(iv){return iv[0] * iv[1];});

// pa7 = <<0,0>, <0,1>, <0,2>>

 

// Create a ParallelArray from canvas.  This creates a PA with shape [w, h, 4],

var pa = new ParallelArray(canvas);

// pa8 = CanvasPixelArray

 

ParallelArray exposes fluent API functions that take an elemental JS function for data manipulation: map, combine, scan, filter, and scatter that return a new ParallelArray. Other functions are scalar - reduce  returns a scalar value & get returns the value located at a given index.

The onus is on the developer to ensure that the elemental function does not defeat data parallelization optimization (avoid global var manipulation, recursion).

For reduce & scan, order is not guaranteed - the onus is on the dev to provide an elemental function that is commutative and associative so that scan will be deterministic – E.g. Sum is associative, but Avg is not.

map

Applies a provided elemental function to each element of the source array and stores the result in the corresponding position in the result array. The map method is shape preserving & index free - can not inspect neighboring values.

// Adding one to each element.

var source = new ParallelArray([1,2,3,4,5]);

var plusOne = source.map(function inc(v) {

    return v+1; }); //<2,3,4,5,6>

combine

Combine is similar to map, except an index is provided. This allows elemental functions to access elements from the source array relative to the one at the current index position. While the map method operates on the outermost dimension only, combine, can choose how deep to traverse - it provides a depth argument to specify the number of dimensions it iterates over. The elemental function of combine accesses the source array & the current index within it - element is computed by calling the get method of the source ParallelArray object with index i as argument. It requires more code but is more expressive.

var source = new ParallelArray([1,2,3,4,5]);

var plusOne = source.combine(function inc(i) { return this.get(i)+1; });

reduce

reduces the elements from an array to a single scalar result – e.g. Sum.

// Calculate the sum of the elements

var source = new ParallelArray([1,2,3,4,5]);

var sum = source.reduce(function plus(a,b) { return a+b; });

scan

Like reduce, but stores the intermediate results – return a ParallelArray whose ith elements is the results of using the elemental function to reduce the elements between 0 and I in the original ParallelArray.

// do a partial sum

var source = new ParallelArray([1,2,3,4,5]);

var psum = source.scan(function plus(a,b) { return a+b; }); //<1, 3, 6, 10, 15>

scatter

a reordering function - specify for a certain source index where it should be stored in the result array.

An optional conflict function can prevent an exception if two source values are assigned the same position of the result:

var source = new ParallelArray([1,2,3,4,5]);

var reorder = source.scatter([4,0,3,1,2]); // <2, 4, 5, 3, 1>

// if there is a conflict use the max. use 33 as a default value.

var reorder = source.scatter([4,0,3,4,2], 33, function max(a, b) {return a>b?a:b; }); //<2, 33, 5, 3, 4>

filter

// filter out values that are not even

var source = new ParallelArray([1,2,3,4,5]);

var even = source.filter(function even(iv) { return (this.get(iv) % 2) == 0; }); // <2,4>

Flatten

used to collapse the outer dimensions of an array into a single dimension.

pa = new ParallelArray([ [1,2], [3,4] ]); // <<1,2>,<3,4>>

pa.flatten(); // <1,2,3,4>

Partition

used to restore the original shape of the array.

var pa = new ParallelArray([1,2,3,4]); // <1,2,3,4>

pa.partition(2); // <<1,2>,<3,4>>

Get

return value found at the indices or undefined if no such value exists.

var pa = new ParallelArray([0,1,2,3,4], [10,11,12,13,14], [20,21,22,23,24])

pa.get([1,1]); // 11

pa.get([1]); // <10,11,12,13,14>

© Geeks with Blogs or respective owner