Tying Mono and OpenCL

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/

Comments 10

  1. Stifu wrote:

    If I understand correctly, GLinq would be a Mono-only thing, unlike PLinq which was invented by Microsoft for .NET 4.0. Right?
    I know this is still quite early, but what about .NET + Glinq? Would it fully work, work less fast (like Mono.Simd), or not work at all? Just curious.

    Posted 18 juin 2010 at 19 h 57 min
  2. Jérémie Laval wrote:

    No, GLinq is also totally managed code (like Mono’s PLinq actually) and can in theory run on .NET too (I don’t see why it wouldn’t).

    Posted 18 juin 2010 at 20 h 10 min
  3. ffox wrote:

    What’s the difference between this and Brahma’s « LINQ to GPU » (http://brahma.ananthonline.net/)?

    Posted 19 juin 2010 at 0 h 12 min
  4. Jérémie Laval wrote:

    I would say it differs on the design goals:

    - less intrusive in the way Linq queries are constructed (same spirit than PLinq)
    - focus solely on OpenCL (OpenCL does the cross-platform heavy lifting)
    - more Linq operator supported
    - expose OpenCL’s OpenGL compatibility

    Posted 20 juin 2010 at 23 h 38 min
  5. Drew Marsh wrote:

    Don’t get me wrong, this is of course very cool, but the big problem with this is the syntactic hacks to get Expressions suck. :(

    Nobody would want to write a real GPGPU kernel like that, they just want to code like they normally do with their favorite language and have it execute on the GPGPU. Naturally you can only use certain language features and extensions within that GPGPU code block, but you know what I mean. The problem is the compilers haven’t added expression support for full method bodies yet. This is a stifling limitation that prevents a « good »/ »natural » .NET GPGPU library from being written today. This is something I blogged about a while ago[1]. I wish the Mono team would work on adding such support to their own compilers for full method body expression generation and I hope Microsoft’s C# team is working on it for their next generation compiler.

    [1] http://blog.hackedbrain.com/archive/2009/08/24/6174.aspx

    Posted 23 sept 2010 at 22 h 58 min
  6. Miha Markic wrote:

    Hi,

    I think NeedConstantAttribute.cs is missing in sources on git.

    Posted 23 sept 2010 at 23 h 21 min
  7. Jérémie Laval wrote:

    @Miha: Fixed, thanks

    Posted 30 sept 2010 at 22 h 26 min
  8. Jérémie Laval wrote:

    @Drew: I totally agree, a fully baked in solution would need compiler supporting a wider range of Expression input than just pure expression lambda. Let’s hope they add that later in the same way they allowed statement in ET with 4.0

    Posted 30 sept 2010 at 22 h 31 min
  9. Drew Marsh wrote:

    I’m really hoping they bring full expression tree support in a 4.x version of the compilers. If we have to wait until 5.0 there’s going to be a lot of missed opportunity for things like this.

    Keep up the great work!

    Cheers,
    Drew

    Posted 01 oct 2010 at 0 h 13 min
  10. Sharron Clemons wrote:

    @Drew: I totally agree, a fully baked in solution would need compiler supporting a wider range of Expression input than just pure expression lambda. Let’s hope they add that later in the same way they allowed statement in ET with 4.0

    Posted 21 déc 2010 at 22 h 23 min

Post a Comment

Your email is never published nor shared. Required fields are marked *