Pass function in other function fast
in
Programming Questions
•
9 months ago
Hi, I'm trying to do modular physical simulation enviroment, and one of things I would like is to pass some user defined fuction to other functions as a parameters. As far as I know, java cannot pass fuction, but it can pass objects, which can have overrriden functions inside. I tryed this on simple example:
static version:
- void arrayAdd( float [] a, float [] b, float [] out ){
- for (int i=0; i<a.length; i++){ out[i] = a[i] + b[i]; }
- }
- void arrayMult( float [] a, float [] b, float [] out ){
- for (int i=0; i<a.length; i++){ out[i] = a[i] * b[i]; }
- }
dynamic (modular) version:
- class Function2 {
- float eval(float a, float b){ return Float.NaN; }
- }
- class FAdd extends Function2 {
- float eval(float a, float b){ return a+b; }
- }
- class FMult extends Function2 {
- float eval(float a, float b){ return a*b; }
- }
- void arrayOp( float [] a, float [] b, float [] out, Function2 func ){
- for (int i=0; i<a.length; i++){ out[i] = func.eval( a[i], b[i] ); }
- }
but
I don't like 2 things about that:
- it is slower than it would be if the function would be inlined in compile time (wich is in principle possible in this case, and I would like force Java JIT compiler to do that )
- It is not very elegant to instantiate objects which contain no data (only a function), I would preffer to pass is as static, but I was unable to do that (it's not possible to pass Class or Static Object to function and use it's methods inside)
I messured speed. For both operations float.mult and float.add the static version is more than 2x faster
static 100000000 [ops] 406.0 [s] 4.06 [ns/op]
dynamic 100000000 [ops] 1188.0 [s] 11.88 [ns/op]
for float.Sqrt the difference is already very small
static 100000000 [ops] 922.0 [s] 9.22 [ns/op]
dynamic 100000000 [ops] 1172.0 [s] 11.719999 [ns/op]
machine - 32bit WinXP, Intel Pentium 3, (I'm not sure about java version)
EDIT - I tested it alos on other machine
New Machine - 64bit ubuntu 12.04LTS, Intel Core5, java version "1.6.0_12-ea, Java(TM) SE Runtime Environment (build 1.6.0_12-ea-b02), Java HotSpot(TM) 64-Bit Server VM (build 11.2-b01, mixed mode)
The results are much better -
static 1000000000 [ops] 1747.0 [s] 1.7470001 [ns/op]
dynamic 1000000000 [ops] 1750.0 [s] 1.75 [ns/op]
- So - I think processor or JIT is already clever enought that ther is no need to optimize this function passing anyhow.
I was asking on stack overflow (
http://stackoverflow.com/questions/14338953/pass-function-as-static-class-for-fast-numerics-in-java ) if it is possible to do somehow static to enable JIT compiler to inline the function.
They recomand some thinks ( pass Class instead of it's instance and use "enums" ) however, it seems that neither of these things does work in processing 2.0b6
APENDIX - this is the code I used for meassuring speed
- final int m = 10;
- final int n = 10000000;
- float t1,t2;
- float [] a,b, out;
- void setup(){
- a = new float[n];
- b = new float[n];
- out = new float[n];
- t1 = millis();
- //for (int i=0;i<m;i++) arrayAdd( a,b, out );
- for (int i=0;i<m;i++) arrayMult( a,b, out );
- t2 = millis();
- println( " static " +(n*m)+" [ops] "+(t2-t1)+" [s] "+ 1000000*((t2-t1)/(n*m))+" [ns/op] " );
- t1 = millis();
- //Function2 func = new FAdd();
- Function2 func = new FMult();
- for (int i=0;i<m;i++) arrayOp( a,b, out, func );
- t2 = millis();
- println( " dynamic " +(n*m)+" [ops] "+(t2-t1)+" [s] "+ 1000000*((t2-t1)/(n*m))+" [ns/op] " );
- }
1