tortoise_hare

One of the cool buzzword these days beside parallel computing is GPGPU as in General Purpose GPU.

The base idea of GPGPU is to allow a programmer to tape in the parallel processing capacities of a GPU to do something different than pixel crushing (even though it mostly boils down to that very application most of time).

GPGPU isn’t new and for a long time vendors have provided their own rather low-level toolkit to program arbitrarily a GPU. As often, someone stepped up one day and proposed a unified API on top of all the vendor specificities. In our case, that API is a standard defined by the Khronos group (think OpenGL) and is named OpenCL.

OpenCL defines both a high-level C API to manipulate GPU (plus other friends) and a C-like intermediate language that is compiled and ultimately run on the device. It’s actually the same model as shader programming.

In the pursuit of Mono world-domination and following the implementation of PLinq that strived to be an easy way for programmer to access the multicore architecture of our processors via Linq, I hereby introduce GLinq (unoriginal acronym for GPU Linq) which this time use your graphic card to execute Linq queries via OpenCL.

GLinq is still much in its infancy and currently only support the Linq’s Select operator but I hope to be able to implement several other operators (at least the classic Where-Aggregate combo). The end goal is also to provide a new set of operator to allow OpenGL code to access the results of the computation without doing a roundtrip between CPU and GPU.

As I said previously, GLinq has the same design goal as PLinq which was to provide a totally new execution model for programmer in the most transparent way possible and with little modification to existing code. In our case, this prerequisite is rather tricky since you are juggling between two totally different worlds.

GLinq tries to provide that seamless experience with two features. The first one is the use of expression trees and C# compiler lambda magic to automatically capture the sense of a C# expression and rewrite it to OpenCL intermediate language. The second one is an automatic mapping of C# types and methods (e.g. Math class functions) to corresponding OpenCL symbols without however sacrificing OpenCL specificities which are also exposed through a C# API (not complete).

Of course, the GLinq API is still a transcription of standard Linq so you use it in the same way via the GpuEnumerable class. At the moment, the only input support are Range and Repeat but that will easily be changed to support any kind of IEnumerable.

Below is an example of the kind of query you can already execute:

var query = GpuEnumerable.Range (-20, 50)
			 .Select ((i) => i * -2 + 3)
			 .Select ((i) => Math.Abs (i))
			 .Select ((i) => ExtraMath.Ldexp ((float)i, 2f))
			 .Select ((i) => (int)i);

foreach (var i in query) 
	Console.Write ("{0}, ", i.ToString ());

From what you can see, there are a lot of select operators here. It comes from the fact that the compiler is only able to convert a pure expression lambda to its corresponding expression tree. You can circumvent this limitation by building yourself the expression tree or by using any compiler/interpreter that outputs expression trees (e.g. IronPython, IronRuby, Bechamel).

On a final note, there is an acknowledged bug in at least NVidia implementation of OpenCL which makes Mono doesn’t play nice with it. This is due to the fact that (most) OpenCL implementations use LLVM for code generation/optimization which in turns mess with Mono internal working.

This problem is going to be fixed in the next NVidia driver iteration but as a work-around you can apply this simple patch to mono. I put SIGWINCHSIGXFSZ there because it looks cool and seems generally unused but any other should do the trick.

Code in its proof-of-concept form is living here: http://git.neteril.org/glinq/