This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Speedup of numerical scripts in the Scala interpreter by wrapping them in a synthetically generated function

5 replies
sterg
Joined: 2009-10-06,
User offline. Last seen 2 years 39 weeks ago.

Hi all,

since the Scala Interpreter implements binding by using the script
variables as fields,
plain script code is executed much slower than code within
functions that use local variables
(e.g. about 20-100 times slower).

I implemented a simple technique in ScalaLab (scalalab281.zip)
that is described in the document SpeedingScalaInterpreter.html
(http://code.google.com/p/scalalab/downloads/list)

Any better idea for that problem?

Best Regards
Stergios

Mark Harrah 2
Joined: 2011-02-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Speedup of numerical scripts in the Scala interpreter by wr

Hi Stergios,

On Thu, 28 Apr 2011 16:39:05 +0300
sterg wrote:

> Hi all,
>
> since the Scala Interpreter implements binding by using the script
> variables as fields,
> plain script code is executed much slower than code within
> functions that use local variables
> (e.g. about 20-100 times slower).

I wouldn't think binding script variables as fields would have any impact. From your description it seems likely that you are sending statements to the interpreter in such a way that each statement is compiled separately. By putting them in the same function, there is only perform one compilation. I am guessing that what you are seeing is a difference in compilation times and not run times, but I don't know how you did your timings or what your code for invoking the interpreter looks like.

-Mark

> I implemented a simple technique in ScalaLab (scalalab281.zip)
> that is described in the document SpeedingScalaInterpreter.html
> (http://code.google.com/p/scalalab/downloads/list)
>
>
> Any better idea for that problem?
>
>
> Best Regards
> Stergios

sterg
Joined: 2009-10-06,
User offline. Last seen 2 years 39 weeks ago.
Re: Speedup of numerical scripts in the Scala interpreter by wr

Hi Mark,

I preprocess the script such that when the export var|val is detected,
only the exported variable is field, and the other are local.
The difference is in run times and is large (i.e. 20-120 times faster
for scripts with a lot of number crunching)

I tested JDK 7 also, it improves field access by about 30-40% but the
difference remains large (i.e. about 15-110 times faster with local
stack based vars).

Stergios

On Thu, 2011-04-28 at 16:07 -0400, Mark Harrah wrote:
> Hi Stergios,
>
> On Thu, 28 Apr 2011 16:39:05 +0300
> sterg wrote:
>
> > Hi all,
> >
> > since the Scala Interpreter implements binding by using the script
> > variables as fields,
> > plain script code is executed much slower than code within
> > functions that use local variables
> > (e.g. about 20-100 times slower).
>
> I wouldn't think binding script variables as fields would have any impact. From your description it seems likely that you are sending statements to the interpreter in such a way that each statement is compiled separately. By putting them in the same function, there is only perform one compilation. I am guessing that what you are seeing is a difference in compilation times and not run times, but I don't know how you did your timings or what your code for invoking the interpreter looks like.
>
> -Mark
>
> > I implemented a simple technique in ScalaLab (scalalab281.zip)
> > that is described in the document SpeedingScalaInterpreter.html
> > (http://code.google.com/p/scalalab/downloads/list)
> >
> >
> > Any better idea for that problem?
> >
> >
> > Best Regards
> > Stergios

Mark Harrah 2
Joined: 2011-02-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Speedup of numerical scripts in the Scala interpreter by wr

On Fri, 29 Apr 2011 16:07:23 +0300
sterg wrote:

> Hi Mark,
>
> I preprocess the script such that when the export var|val is detected,
> only the exported variable is field, and the other are local.
> The difference is in run times and is large (i.e. 20-120 times faster
> for scripts with a lot of number crunching)
>
> I tested JDK 7 also, it improves field access by about 30-40% but the
> difference remains large (i.e. about 15-110 times faster with local
> stack based vars).

It would help to see how you are invoking the interpreter. I ran the code in the script directly in the interpreter and it took about 20 ms.

I did:

scala> var m,k,l = 0; var sm = 0.0;
m: Int = 0
k: Int = 0
l: Int = 0
sm: Double = 0.0

scala> import System.{currentTimeMillis => now}
import System.{currentTimeMillis=>now}

scala> def time(f: => Any) = {
| val s = now
| val result = f
| println( result +" in " + (now - s) + " ms")
| }
time: (f: => Any)Unit

scala> time { ; sm }
1.275125E10 in 20 ms

I am guessing that tic and toc in your script are start timer and read elapsed time. If so, and if you are not doing anything special with providing statements to the interpreter, you are probably timing compilation time.

-Mark

> Stergios
>
> On Thu, 2011-04-28 at 16:07 -0400, Mark Harrah wrote:
> > Hi Stergios,
> >
> > On Thu, 28 Apr 2011 16:39:05 +0300
> > sterg wrote:
> >
> > > Hi all,
> > >
> > > since the Scala Interpreter implements binding by using the script
> > > variables as fields,
> > > plain script code is executed much slower than code within
> > > functions that use local variables
> > > (e.g. about 20-100 times slower).
> >
> > I wouldn't think binding script variables as fields would have any impact. From your description it seems likely that you are sending statements to the interpreter in such a way that each statement is compiled separately. By putting them in the same function, there is only perform one compilation. I am guessing that what you are seeing is a difference in compilation times and not run times, but I don't know how you did your timings or what your code for invoking the interpreter looks like.
> >
> > -Mark
> >
> > > I implemented a simple technique in ScalaLab (scalalab281.zip)
> > > that is described in the document SpeedingScalaInterpreter.html
> > > (http://code.google.com/p/scalalab/downloads/list)
> > >
> > >
> > > Any better idea for that problem?
> > >
> > >
> > > Best Regards
> > > Stergios

sterg
Joined: 2009-10-06,
User offline. Last seen 2 years 39 weeks ago.
Re: Speedup of numerical scripts in the Scala interpreter by wr

Mark,

I use the Scala interpreter from within my ScalaLab project

(http://code.google.com/p/scalalab/)
and not the official REPL one.

Therefore many instructions are Matlab-like extensions that do not
operate with the official Scala REPL.

You can try from within ScalaLab for example direct script code:

// Ikeda map
close("all")
val R = 1; val C1 = 0.4; val C2 = 0.9; val C3 = 6

tic;
var N=500000;

var x = new Array[Double]( N)
var y = new Array[Double]( N)
x(0)=0.12; y(0) = 0.2;

var k = 1;
var km = 0;
var tau=0.0; var sintau=0.0; var costau=0.0
while (k< N) {
km=k-1
tau = C1-C3/(1+x(km)*x(km)+y(km)*y(km))
sintau = sin(tau); costau = cos(tau);
x(k) = R+C2*(x(km)*costau-y(km)*sintau)
y(k) = C2*(x(km)*sintau+y(km)*costau)
k += 1

}

var tm = toc();
scatterPlotsOn(); // display points only, not the connecting lines
plot(x, y);
title("Scala Time for Ikeda map "+tm);

// My Computer: 0.665 sec

... and code with the "export" statement

// Ikeda map
close("all")
val R = 1; val C1 = 0.4; val C2 = 0.9; val C3 = 6

tic;
var N=500000;

var x = new Array[Double]( N)
var y = new Array[Double]( N)
x(0)=0.12; y(0) = 0.2;

var k = 1;
var km = 0;
var tau=0.0; var sintau=0.0; var costau=0.0
while (k< N) {
km=k-1
tau = C1-C3/(1+x(km)*x(km)+y(km)*y(km))
sintau = sin(tau); costau = cos(tau);
x(k) = R+C2*(x(km)*costau-y(km)*sintau)
y(k) = C2*(x(km)*sintau+y(km)*costau)
k += 1

}

export var tm = toc()
scatterPlotsOn(); // display points only, not the connecting lines
plot(x, y);
title("Scala Time for Ikeda map "+tm);

// My Computer: 0.096 sec

Regards

Stergios

Mark Harrah 2
Joined: 2011-02-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Speedup of numerical scripts in the Scala interpreter by wr

On Fri, 29 Apr 2011 18:15:45 +0300
sterg wrote:

> Mark,
>
> I use the Scala interpreter from within my ScalaLab project
>
> (http://code.google.com/p/scalalab/)
> and not the official REPL one.
>
> Therefore many instructions are Matlab-like extensions that do not
> operate with the official Scala REPL.

As far as I can tell, this is not relevant. The script you originally posted consists only of plain Scala code and when I entered it in the official REPL, it took 20 ms. This suggests that field access time doesn't matter. A reasonable explanation is that you are measuring compilation time.

I assume you are sending statements to the REPL so that it compiles a statement, runs it, compiles the next, runs it, and so on. (This is the default behavior of the REPL.) I also assume tic records the current time and toc returns the elapsed time since tic. So, for your script, the REPL compiles and runs the tic statement (recording the time) and then _compiles_ and runs the while statement. Then, it compiles and runs the toc statement. This means that between tic and toc there is at least one compilation.

When you rewrite it for 'export', you are probably merging tic and toc into a single evaluation. The actual evaluation time doesn't change, just your measurement technique.

To show this is not the case, you'd have to show what tic/toc do, how you take user input and send it to the REPL (using the interpret method? preprocessing?), and explain why you aren't measuring compilation time.

-Mark

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland