-- Discrete Markov Chain Sample Example 
using io
def main() 
    n = 2000
    niter = 500
    M = get_stocastic(n,n)     -- initialize the matrix
    v = get_distribution(n)    -- initialize the vector of distribution
    >>> M, v                   -- move to desired device
    for i = 1 : niter
       v = mat_mulvec(M, v)    -- compute in device
    end
    <<< v                      -- recovery data from device  
    println(stdout, v)                           
end       

What is Neblina?

Neblina is a scientific and numerical programming language that aims to create a substantially transparent layer on the programming of parallel computing environments equipped with heterogeneous architectures, such as CPUs and GPUs.
Fig1. A view of Neblina parse/execution process.
Increasing productivity in parallel and high performance computing is a current research area. We can mention the project named High Productivity Computing Systems (HPCS) of DARPA, one of whose goals is to develop a new generation of high productivity computing. This project emerged the following programming languages with this purpose: X10 , Fortress and Chepel. Howerever in this languages, the user need know about paralelism (either task or data paralelism). Only Chepel support GPGPU architetures. The commom approach to increase the produtivity in parallel CPU program is the use of compile directives and annotations on existing languages. Accelerator, Nested and Copperhead use data paralelism model to facilitating the GPU development. Our approach differs from these previous languages since Neblina need not require any knowledge about parallelism. The approaches closest to the proposal of this work are SaC, Chesnut, Matlab Jacket. However, these languages have important differences in our work. SaC (Single Assignment C), Chesnut and Jacket generate a Cuda code from a high level functional language. In this case, only Nvidia platforms can be used differently of our work that can be used in many heterogeneous platforms.

Download

Neblina is a free open source software and can be used for academic, commercial and others purposes without restrictions.

FileVersionDateSHA1
neblina-1.1.13.tar.gz 1.1.13 2015-09-02 bfa821264ede90027990166cac174c2466708e13

Compile and Install

You need at least one OpenCL platform installed.
$ ./configure
$ make 
# make install
Currently, Neblina is being used in HiPerWalk High Performance Quantum Walk Simulator.

Getting Started with Neblina

Neblina is a language focused on establishing a parallel computing layer using minimal knowledge of the user about parallel programming. For those who are programming in Neblina, the operations are seen as sequential operations. independently of the architecture processing platform or vendor, the Neblina interpreter sends the data to the parallel processing unit (either CPU or GPU). This is done in a transparent way using OpenCL paralell API. Another purpose is to provide an open environment for programming in a heterogeneous processing platforms. Users can also extend the language by creating new functions. Particularly, operations involving arrays (matrices and vectors) are operations, in general case, with greater computational demand. The Neblina programming language aims to be simple and easily to manipulate. Basic structure is similar to traditional programming languages, such as C, Java and Python. It has dynamic typing that allows greater flexibility in programming (like Python and Lua). The variables don't have types, they have values. We prefer not to use models of languages such as LISP or Prolog. This could discourage non-programmers or professionals from different areas of language use Neblina. We try to have a simple language but familiar. The Neblina language supports much of the conventional statements (conditional structure, loop iteration, ...). Each statements, has implicit begin and the end marked with the reserved word end. Our goal is to have a language not very prolific, however, have a pleasant and intelligible language to describe codes. All Neblina programs have a main function (such as C) to start program. See the automatic generated GNU Bison Automaton Report for a detailed view of Neblina syntax. Here some Neblina codes to get a initial contact with syntax.
def main()
    n = 4             -- an integer 
    V = float[3]      -- vector of float point variable with 3 elements
    M = int[n,n]      -- integer matrix 4x4 
end
Example of for loop and if statement.
using io
def main()    
    for i = 0 : 10
        if (i % 2) == 0:        
            println( i ) -- print only even numbers from 0 to 10 
        end
    end
end
The same example now using while statement.
using io
def main()    
    i = 0
    while i <= 10:    
        if (i % 2) == 0:        
            println( i ) -- print only even numbers from 0 to 10 
        end
        i = i + 1
    end
end
Defining functions and get the returns.
def foo()
    return 1, 2, 3
end

def main()
    a, b, c = foo()
    a, b = b, a  -- swap values
end
Moving data between the host and the device.
    >>> x, y                -- move the vectors to device
    x = vec_add( x, y )     -- compute the vector addition
    <<< x                   -- recovery the vector x from device

Neblina Build-in Functions

Here a list of Neblina build-in functios and their respective packages. Functions marked with package std does not need to be included. These are automatically included.

Function Description Example Package
open(filename,mode) like C/C++ fopen. filename can be a path to file and mode can be read "r", write "w". Return a file descriptor. f = open("file.txt", "r") io
close(fdesc) close a file descriptor close( f ) -- opened before io
print([fdesc], str) print str to file descrited by fdesc. If fdesc is omitted then it print to stdout. print( f, "str" ) io
println([fdesc], str) As the same of print but it's break a line. println( "Hello World!" ) io
read([fdesc], var) Read from file a variable and return a value read. a = read(f, a) io
fmtfloat(nplaces) Set a number of decimal places to float variables fmtfloat( 2 ); print( 1.123 ) -- will print 1.12 io
sin(value) compute sine of a value r = sin(3.14) math
cos(value) compute cosine of a value r = cos(2.73) math
tan(value) compute tangent of a value r = tan(10.73) math
sinh(value) compute hyperbolic sine of a value r = sinh(3.14) math
cosh(value) compute hyperbolic cosine of a value r = cosh(2.73) math
tanh(value) compute hyperbolic tangent of a value r = tanh(10.73) math
asin(value) compute arc sine of a value r = asin(3.14) math
acos(value) compute arc cosine of a value r = acos(2.73) math
atan(value) compute arc tangent of a value r = atan(10.73) math
deg(value) convert radians to degrees r = deg(4.93) math
rad(value) convert degrees to radians r = rad(2.2) math
log(value[, base]) compute logarithm of value using base r = log(4,2.71) math
floor(value) rounding to floor r = floor(1.9) -- r is 1 math
ceil(value) rounding to ceil r = ceil(1.1) -- r is 2 math
round(value) rounding to nearest int r = round(1.8) -- r is 2 math
sqrt(value) compute square root of value r = sqrt(64) math
exp(value) compute e^value r = exp(4.83) math
abs(value) compute absolute of value r = abs(-83.23) math
seed(value) initialize pseudo random sequence seed(738491023) math
random([init, end]) generate a pseudo random number in specific range r = random(0,10) math
sec() Returns the number of seconds since 1970-01-01 00:00:00 +0000 (UTC) r = sec() time
milli() Returns the number of milliseconds since 1970-01-01 00:00:00 +0000 (UTC) r = mili() time
micro() Returns the number of microseconds since 1970-01-01 00:00:00 +0000 (UTC) r = sec() time
type(v) return a type as a string of a value s = type("LNCC") std
toint(v) Convert v to int r=tofloat(1.9203) -- return 1 std
tofloat(v) Convert v to float r=tofloat("1.849") std
tostr(v) Convert v to string r=tostr(0x89) std
c(re,im) Create a complex number with real part re and complex part re c = c(1,3.3) std
real(c) Return as a float the real part of a complex number r=real(c) std
imag(c) Return as a float the complex part of a complex number r=imag(c) std
conj(c) Return a complex conjugate of a complex number c=conj(c(1,2)) std
upper(s) Return a upper case string from s s=upper("lncc") std
lower(s) Return a lower case string from s s=lower("LNCC") std
len(s) Return a size of string r=len("LNCC") std
at(s,v) Return a char in position v of string s p=at("LNCC",2) -- return "N" std
vec_add(v1,v2) Return the sum of vectors. v1+v2 v=vec_add(v1,v2) std
vec_sub(v1,v2) Return the subtraction of vectors. v1-v2 v=vec_sub(v1,v2) std
vec_sum(v1) Return the sum of values in v1 r=vec_sum(v1) std
vec_dot(v1,v2) Return the inner product of v1 and v3 r=vec_dot(v1,v2) std
vec_norm(v1) Return norm L^2 of vector v1 r=vec_norm(v1) std
vec_mulsc(v1,r) Return the product of v1 by a float r v=vec_mulsc(v1,r) std
mat_add(m1,m2) Return the sum of matrix. m1+m2 m=mat_add(m1,m2) std
mat_sub(m1,m2) Return the subtraction of matrix. m1-m2 m=mat_sub(m1,m2) std
mat_mul(m1,m2) Return the multiplication of matrix m1 and m2 m=mat_mul(m1,m2) std
mat_mulvec(m1,v1) Return the multiplication of a matriz by a vextor v = mat_mulvec(m1,v1) std
mat_mulsc(m1,r) Return the product of m1 by a float r v=mat_mulsc(m1,r) std
mat_transp(m1) Return the transpose matrix m = mat_transp(m1) std
nrows(m) Return the number of rows of a matrix m r=nrows(m) std
ncols(m) Return the number of columns of a matrix m r=ncols(m) std

C Integration

The Neblina programming language allows to add functions written in C language and use them. To add functions written in C is necessary to create a package before. Neblina has such functions for such integration. Here primitive types of Neblina language.
typedef enum  {
        T_STRING,      // basic string 
        T_INT,         // integer
        T_FLOAT,       // float point
        T_COMPLEX,     // complex numbers
        T_ADDR,        // address 
                       //     (for internal byte code use)
        T_NDEF,        // to inicialize some variable 
                       //      (for internal byte code use)
        T_CFUNC,       // pointer to a C function 
                       //      (for internal byte code use)
        T_VECTOR,      // native neblina vector
        T_MATRIX,      // native neblina matrix
        T_FILE,        // file handler 
        T_ANY          // arbitrary type
} data_type;
Now an example of C function integration with Neblina. First, we create a package with one function only. Then, we define number and types of input and output values. Finally, we add this function on package called io.
void ** neblina_open (void ** input, int * status);    
package_t * getPackage() {
    package_t * pkg = package_init( 1,   // number of functios in package
                                 "io" ); // name of package
    data_type input_type[]  = { T_STRING, T_STRING };
    data_type output_type[] = { T_FILE };
    pkg->functions[0] = 
    package_new_func("open",         // name of function that will be used
                      2,             // number of input parameters
                      1,             // number of output values
                      input_type,    // type of input values  
                      output_type,   // type of output values
                      neblina_open );// callback function that will be called
   return pkg;                                   
}

Become a Neblina developer

You can help the Neblina Interpreter become better software. Contact the pcslara@lncc.br to more informations. The source code for Neblina is in the public domain.