Giter VIP home page Giter VIP logo

ocl's Introduction

ocl

ocl is a minimalist library that dynamically (at run time) converts decorated Python functions into C99, OpenCL, or JavaScript. In the C99 case, it also uses distutils to compile the functions to machine language and allow you to run the compiled ones instead of the interpreted ones. In the OpenCL case you can run the compiled ones using pyOpenCL.

It consists of a single pure-Python file containing about 600 lines of code. Some of the ocl functionalities overlap with Cython, CLyter, and Pyjamas.

It is based on the Python ast module, and the these fantastic libraries:

The conversion is purely syntatical and assumes all symbols used in the code are defined on the target. It only check for undefined variables used in assignments. You can only use types which are defined on the target. This means you can use a list or hash table if converting to JS not but if converting to C99 or OpenCL. Functions can only return local variables.

Examples:

Convert Python Code into C99 Code

from ocl import Compiler
c99 = Compiler()
@c99.define(a='int', b='int')
def f(a, b):
    for k in range(n):
        while True:
            break
        if k==0 or k!=0 or k<0 or k>0 or not k==0 or \
           k>=0 or k<=0 or k is None or k is not None:
            continue
    c = new_int(a+b)
    printf("%i + %i = %i", a, b, c)

    d = new_ptr_int(CAST(prt_int,ADDR(c)))
    c = REFD(d)
    return c
print c99.convert(headers=False, constants=dict(n=10))

Output:

int f(int a, int b) {
    long k;
    int c;
    int* d;
    for (k=0; k<10; k+=1) {
        while (1) {
            break;
        }
        if (((k == 0) || ((k != 0) || ((k < 0) || ((k > 0) || ((! (k == 0)) ||
            ((k >= 0) || ((k <= 0) || ((k == None) || (k != None)))))))))) {
            continue;
        }
    }
    c = (a + b);
    printf("%i + %i = %i",a,b,c);
    d = (int*)((&(c)));
    c = (*(d));
    return c;
}

Notice variables are declared via new_int or similar pseudo-function. Use new_ptr_float to define a float* or new_ptr_ptr_long for a long**, etc. The convert allows to pass constants defined in the code (n in the example). You must define the types of function arguments in the decorator "c99". The return type is inferred from the type of the object being returned (you must retrun a variable defined within the function or None for void). You can decorate more than one function and get the complete code.

new_<type>, range, ADDR (address of), REFD (obj referenced by), CAST, True, False, and None are keywords.

Convert Python Code into C99 Code and replace function with compiled one

from ocl import Compiler
c99 = Compiler()
@c99.define(n='int')
def factorial(n):
    output = 1
    for k in range(1,n+1):
        output = output*k
    return output
compiled = c99.compile()
print compiled.factorial(10)
assert factorial(10) == compiled.factorial(10)

The function call compiled.factorial(10) runs the C-compiled version of the factorial function. .compiled() creates and imports a python module containing all the decorated functions. It returns a module with the compiled functions, compiled. Compiled functions can call other compiled functions.

Convert Python Code into OpenCL code and run it with PyOpenCL

(requires pyopencl to run)

Here is a solver for the Laplace equation "d^2 u = d in 2D"

from ocl import Compiler
opencl = Compiler()
@opencl.define_kernel(
           w='global:ptr_float',
           u='global:const:ptr_float',
           q='global:const:ptr_float')
def solve(w,u,q):
    x = new_int(get_global_id(0))
    y = new_int(get_global_id(1))
    site = new_int(x*n+y)
    if y!=0 and y!=n-1 and x!=0 and x!=n-1:
        up = new_int(site-n)
        down = new_int(site+n)
        left = new_int(site-1)
        right = new_int(site+1)
        w[site] = 1.0/4*(u[up]+u[down]+u[left]+u[right] - q[site])
print opencl.convert(constants=dict(n=300))

Output:

__kernel void solve(__global float* w, __global const float* u, __global const float* q) {
    int right;
    int site;
    int up;
    int down;
    int y;
    int x;
    int left;
    x = get_global_id(0);
    y = get_global_id(1);
    site = ((x * 300) + y);
    if (((y != 0) && ((y != (300 - 1)) && ((x != 0) && (x != (300 - 1)))))) {
        up = (site - 300);
        down = (site + 300);
        left = (site - 1);
        right = (site + 1);
        w[site] = ((1.0 / 4) * ((((u[up] + u[down]) + u[left]) + u[right]) - q[site]));
    }
}

Here __kernel, __global, and __local are OpenCL modifiers. get_global_id and get_global_size are OpenCL specific functions. A more comlete example that puts this code into context and runs it with PyOpenCL can be found in the example_laplace_opencl.py file.

Convert Python Code into Javascript Code

(works with jQuery and every other JS library)

from ocl import Compiler, JavaScriptHandler
js = Compiler(handler=JavaScriptHandler())
@js.define()
def f(a):
    a = new(array(1,2,3,4))
    v = [1, 2, 'hello']
    w = {'a': 2, 'b': 4}
    def g():
        try:
            alert('hello')
        except e:
            alert(e)
    jQuery('button').click(lambda: g())
print js.convert(call='f')

Output:

var f = function(a) {
    var a = new array(1,2,3,4);
    var v = [1, 2, "hello"];
    var v = [1, 2, "hello"];
    var w = {"a":2, "b":4};
    var g = function() {
        try {
            alert("hello");
        catch (e) {
            alert(e);
        }
    }
    jQuery("button").click(function () { g() });
}
f();

In the JS case, the call="f" option tells JS to call the newly defined function "f". Notice undefined assigned variables are automatically made local with var.

Supported control structures include def, if..else, for ... range, while, try ... except, break, continue.

How does it work?

It uses the meta library to convert python code into an "Abstract Syntax Tree". It then calls a handler (C99Handler by default or JavaScriptHandler) which converts the AST into the target language.

In the C99 case, c99.compile() uses distutil to compile the source to a binary Python module and it imports the module. The module is returned. A more complex of a C implementation of Black-Scholes solver can be found in example_black_scholes.py.

OpenCL code is just C99 code with special types modifiers. ocl provides the Device class which allows interaction with GPU devices (and other OpenCL devices) using the myOpenCL library. This handles mapping of host memory into device memory, JIT compilation of OpenCL code, deploying and running on OpenCL devices. A complete example is in the example_laplace_opencl.py file.

ocl's People

Contributors

mdipierro avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.