/balisc

A fresh (experimental) look at Scilab 6.x

Primary LanguageScilab

Balisc

  • provides a fresh (experimental) look at Scilab 6.x, i.e. it
  • detects SIMD extensions (SSE2/SSE4/AVX/...) and uses it (currently, just a little bit)
  • improves run-time performance of various functions in string, elementary_functions, ... modules
  • tries cleaning and simplification of code base (huge on-going task)
  • will try to get rid of legacy redundancies and inconsistencies at a faster pace
  • dropped MSVC support and will switch to MINGW/MSYS2 for Windows support (in the long run)
  • currently runs on Linux 64bit only, but is fully compatible with Scilab 6.x (at least at the language level)
  • ...

Is it for me?

We don't know, but you may try running this

A=string(rand(1000,1000));
tic;B=strcat(A);toc
tic;strsubst(B,"3","X");toc
S=sprand(5000,5000,0.001);
tic;S==0.5;toc

under current Scilab 6.x. In the meantime, you might think about compiling Balisc by yourself (cf. below) and executing the very same instuctions on your freshly built Balisc. This could confront you with results like this.

--> A=string(rand(1000,1000));
--> tic;B=strcat(A);toc
 ans  =
   0.063398
--> tic;strsubst(B,"3","X");toc
 ans  =
   0.095663
--> a=sprand(5000,5000,0.001);
--> tic;a==0.5;toc
 ans  =
   0.233446

Please, don't take these examples too seriously, they are just extremes chosen for pedagogic reasons. Scilab is a very powerful and comprehensive tool.

You want to Protect Just One Variable?

With the unique functions protect, unprotect, and isprotected of Balisc, you might do this

--> x=123;y=456;
--> protect x
--> x=0
Redefining permanent variable.
--> y=1
 y  = 
   1.
--> isprotected(["x" "y"])
 ans  =
  T F
--> unprotect x
--> x=0
 x  = 
   0.

Please note, these functions have been added very recently (cf. #366 #420), thus they are not tested very well and might need some polishing. However, can you do the same thing using predef in current Scilab 6.x?

You are working with Complex Numbers and Expect Consistent Results?

With Balisc your calculations will yield complex infinity and undefined results consistently with respect to the complex plane. Therefore, a result with a Nan real and a Nan imaginary part is undefined and a result with at least one Inf part corresponds to complex infinity.

--> 0/(0+0*%i)
 ans  =
   Nan + Nani
--> (0+0*%i)/(0+0*%i)
 ans  =
   Nan + Nani
--> 1/(0+0*%i)
 ans  =
   Inf + Nani
--> (1+0*%i)/(0+0*%i)
 ans  =
   Inf + Nani

Please note, this is just how nowadays the complex arithmetics, provided by a decent C/C++ compiler, works. These rectifications have been added very recently (cf. #390 #402).

You Expect (Vectorized) Code to be Executed Faster?

Heavily inspired by this simple benchmark, we have assembled the following two functions heat_loop and heat_vect.

// naive (not vectorized)
function u = heat_loop(nx, nt, dx, dt, D, v)
    u=42*zeros(nx,1);
    u_next=u;
    for it=1:nt
        for ix=2:nx-1
            u_next(ix)=u(ix)+D*dt/(dx*dx)*(u(ix+1)-2*u(ix)+u(ix-1))-v*dt/dx*(u(ix+1)-u(ix));
        end
        u=u_next;
    end
endfunction

// vectorized
function u = heat_vect(nx, nt, dx, dt, D, v)
    u=42*zeros(nx, 1);
    u_next=u;
    for it=1:nt
        u_next(2:nx-1)=u(2:nx-1)+D*dt/(dx*dx)*(u(3:nx)-2*u(2:nx-1)+u(1:nx-2))-v*dt/dx*(u(3:nx)-u(2:nx-1));
        u=u_next;
    end
endfunction

We have run them under Scilab 6.0.1 and current Balisc and got the following timing results.

Scilab 6.0.1
--> tic();heat_loop(1e3,1e4,1e-1,1e-8,1,1);t_loop=toc()
 t_loop  = 
   101.15152
--> tic();heat_vect(1e3,1e4,1e-1,1e-8,1,1);t_vect=toc()
 t_vect  = 
   0.97665
--> t_loop/t_vect
 ans  =
   103.56988
Balisc (current)
--> tic();heat_loop(1e3,1e4,1e-1,1e-8,1,1);t_loop=toc()
 t_loop  = 
   80.622409
--> tic();heat_vect(1e3,1e4,1e-1,1e-8,1,1);t_vect=toc()
 t_vect  = 
   0.491977
--> t_loop/t_vect
 ans  =
   163.87435

The vectorized code heat_vect was executed 100 times faster under Scilab 6.0.1 and even 160 times faster under Balisc in comparison to vect_loop. Furthermore, heat_vect was executed two times faster under Balisc in direct comparison to Scilab 6.0.1.

Please don't expect to achieve this speed-up for every piece of code you can think of! This is just a motivating little spot light!.

You Want Simple Object Oriented Programming

A few lines of code are necessary for simple object oriented programming, have a look at the following (truly minimal) example implemenation of a numberobject with just one member function square.

// constructor for 'number'
function o = number(v)
  o = tlist(['number','value'],v)
end

// overload 'extract' op for type 'number' 
function mf = %number_e(m, o)
  global this
  this = o
  mf = funref(typeof(this) + '#' + m)
  if mf == []
    error("Undefined method: ''%s#%s''.", typeof(this), m)
  end
end

// a simple member function
function y = number#square()
  global this
  y = this.value^2
end

This number object can be used really easily, e.g.:

--> N=number(9);
--> N.square
 ans  =

   81.

--> N.value=7;

--> N.square
 ans  =

   49.

--> N.cube
at line     6 of function %number_e 

Undefined method: 'number#cube'.

If you are in need of more member functions, e.g. cube, then just define them, e.g. do function y=number#cube(),...,end.

Try some of Scilab's Benchmarks

Scilab 6.X is shipped with a sparse set of benchmarks only for some its modules. You may run them as follows:

--> [n,t]=bench_run(<Benchmark>); sum(t)/1000
...
 ans  =
   <Time in s>

We have done that, and got the following results:

Benchmark Scilab 6.0.1 Balisc 0 Difference Scilab 6.0.2 Balisc 1 Difference
"ast" -- -- -- 6.91 5.79 - 16 %
"core" 35.16 30.82 - 12 % 36.01 28.87 - 20 %
"elementary_functions" 41.49 26.90 - 35 % 43.02 25.91 - 40 %
"fileio" 47.19 6.25 - 86 % 5.74 5.38 - 6 %
"string" 140.89 51.06 - 63 % 144.69 52.19 - 64 %
"time" 91.76 24.51 - 73 % 66.53 20.44 - 69 %

Please note, that the "elementary_functions" benchmark is not the same as that of Scilab 6.X (cf. balisc/scilab/modules/elementary_functions/tests/benchmarks/).

Furthermore, take these results just as an indicator, that Balisc might perform significantly better than Scilab 6.X.

Your mileage may vary! Things are currently really in an experimental and work-in-progress state!

Compilation with GCC for Linux x86_64

You may want to follow the the instructions Compilation of Scilab (probably not up-to-date), or follow the procedure described below, which assumes, that you have installed all required non-Java stuff on your system (Dependencies of Scilab 5.X, probably not up-to-date).

Please note, that Balisc additionally needs SLEEF (SIMD Library for Evaluating Elementary Functions), under Ubuntu you may install the SLEEF library from this PPA.

What else is needed? For the time being, just run configure (cf. below), and see what is missing, install the missing libraries, and re-run configure ... and so on ...

  • cd <PATH>
  • git clone https://github.com/rdbyk/balisc.git balisc
  • cd balisc/scilab
  • svn --force checkout https://github.com/scilab/scilab-prerequirements.git/trunk/linux_x64/ .
  • mv usr usr_DEV
  • mv lib lib_DEV
  • mkdir -p lib/thirdparty
  • cp lib_DEV/thirdparty/libjogl_*.so lib/thirdparty
  • ./configure --with-eigen-include=<PATH>/balisc/scilab/usr_DEV/include
  • make

Issues and Pull Requests

Both are welcome! For the time being, we have the following focus

  • improvement of run-time performance and maintainability
  • simplification of code base
  • compilation under Linux x86_64 GCC
  • building of binary packages (Debian, Ubuntu, ...)
  • ...