This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Speed issue?


There are many cases where Kawa is not going to generate as fast a code as writing in Java.

The big hit here is almost certainly dominated by the difference between using the primitive type double arithmetic vs. using Kawa's numeric tower in the inner loop.

If you convert:

>  (set! profit (+ profit (- (* c (- Xj Yj))
>                            (* h Yj))))
>  (if (and (< Yj s) (< (*:nextDouble (Inv-streamOrder inv)) p))
>      (begin (set! profit (- profit (+ K (* k (- S Yj)))))
>             (set! Xj S))

to test out the impact of that portion you could either call the native Java version from Kawa, and/or you can try adding some type declarations to the Kawa variables (which will have a relatively smaller effect):

http://www.gnu.org/software/kawa/Declaring-Types-of-Variables.html

A primitive double is declared as <double>:

http://www.gnu.org/software/kawa/Standard-Types.html

Jim

David St-Hilaire wrote:

Hi all!

I'm currently interfacing a Java library for stochastic simulations (SSJ). I
successfully translated a simple test sample written in Java. The thing is that
it takes about 0.5 secs for the execution of the java code and about 25 secs for
the execution of its Kawa counterpart...

Is it always like that? Why is that a java library runs slower when executed
from kawa? It is disapointing because I might not be able to use kawa for my
works if it keeps that 50 times slower ratio for bigger simulations... :(

Thanks for the help!

PS: Ive sent in attachement both the original java code and the translation I
made... The code is pretty simple, but maybe the slowness comes from my
translation??

Thanks!!

David


------------------------------------------------------------------------


;; Definitions pour simplifie la traduction:
(define-syntax for (syntax-rules (=)
((_ (var = init) limit exp1 exps ...)
(let loop ((var init))
(if (<= var limit)
(begin (begin exp1 exps ...)
(loop (+ var 1))))))


    ((_ init limit exp1 . exps)
     (let loop ((var init))
             (if (< var limit)
                 (begin (begin exp1 . exps)
                        (loop (+ var 1))))))
    ))

(define-syntax pp
  (syntax-rules ()
    ((pp arg) (begin (display arg) (newline)))))

(define-record-type Inventory
  (new-Inv lam c h K k p genDemand streamDemand streamOrder statProfit)
  Inv?
  (lam Inv-lam)
  (c Inv-c Inv-set!-c)
  (h Inv-h Inv-set!-h)
  (K Inv-K Inv-set!-K)
  (k Inv-k Inv-set!-k)
  (p Inv-p Inv-set!-p)
  (genDemand Inv-genDemand Inv-set!-genDemand)
  (streamDemand Inv-streamDemand Inv-set!-streamDemand)
  (streamOrder Inv-streamOrder Inv-set!-streamOrder)
  (statProfit Inv-statProfit Inv-set!-statProfit))

;; Debut de la traduction du code:

(define (make-Inventory lam c h K k p)
  (let ((streamDemand (<umontreal.iro.lecuyer.rng.MRG32k3a>))
        (streamOrder (<umontreal.iro.lecuyer.rng.MRG32k3a>)))
    (new-Inv lam c h K k p
             (<umontreal.iro.lecuyer.randvar.PoissonGen>
              streamDemand
              (<umontreal.iro.lecuyer.probdist.PoissonDist> lam))
             streamDemand
             streamOrder
             (<umontreal.iro.lecuyer.stat.Tally> "stats on profit"))))

(define (simulateOneRun inv m s S)
(let ((Xj 0)
(Yj 0)
(profit 0)
(c (Inv-c inv))
(p (Inv-p inv))
(h (Inv-h inv))
(k (Inv-k inv))
(K (Inv-K inv)))
(for 0 m (set! Yj (- Xj (*:nextInt (Inv-genDemand inv))))
(if (< Yj 0) (set! Yj 0))
(set! profit (+ profit (- (* c (- Xj Yj))
(* h Yj))))
(if (and (< Yj s) (< (*:nextDouble (Inv-streamOrder inv)) p))
(begin (set! profit (- profit (+ K (* k (- S Yj)))))
(set! Xj S))
(set! Xj Yj)))
(/ profit m)))


(define (simulateRuns inv n m s S)
  (for 0 n
       (*:add (Inv-statProfit inv) (simulateOneRun inv m s S))))

(define (main)
  (let ((timer (make <umontreal.iro.lecuyer.util.Chrono>))
        (sytem (make-Inventory 100 2 0.1 10 1 0.95)))
    (simulateRuns sytem 500 2000 80 200)
    (*:setConfidenceIntervalStudent (Inv-statProfit sytem))
    (pp (*:report (Inv-statProfit sytem) 0.9 3))
    (display "Total CPU time: ") (pp (*:format timer))))

(main)


------------------------------------------------------------------------


import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.randvar.*;
import umontreal.iro.lecuyer.probdist.PoissonDist;
import umontreal.iro.lecuyer.stat.Tally;
import umontreal.iro.lecuyer.util.*;

public class Inventory {

    double lambda;  // Mean demand size.
    double c;       // Sale price.
    double h;       // Inventory cost per item per day.
    double K;       // Fixed ordering cost.
    double k;       // Marginal ordering cost per item.
    double p;       // Probability that an order arrives.

RandomVariateGenInt genDemand;
RandomStream streamDemand = new MRG32k3a();
RandomStream streamOrder = new MRG32k3a();
Tally statProfit = new Tally ("stats on profit");
public Inventory (double lambda, double c, double h, double K, double k, double p) {
this.lambda = lambda; this.c = c; this.h = h; this.K = K; this.k = k; this.p = p;
genDemand = new PoissonGen (streamDemand, new PoissonDist (lambda));
}


// Simulates the system for m days, with the (s,S) policy,
// and returns the average profit per day.
public double simulateOneRun (int m, int s, int S) {
int Xj = S, Yj; // Stock in the morning and in the evening.
double profit = 0.0; // Cumulated profit.
for (int j=0; j<m; j++) {
Yj = Xj - genDemand.nextInt(); // Subtract demand for the day.
if (Yj < 0) Yj = 0; // Lost demand.
profit += c * (Xj - Yj) - h * Yj;
if ((Yj < s) && (streamOrder.nextDouble() < p)) { // We have a successful order.
profit -= K + k * (S - Yj);
Xj = S;
}
else
Xj = Yj;
}
return profit / m;
}


// Performs n independent simulation runs of the system for m days,
// with the (s,S) policy, and returns a report with a 90% confidence // interval on the expected average profit per day.
public void simulateRuns (int n, int m, int s, int S) {
for (int i=0; i<n; i++)
statProfit.add (simulateOneRun (m, s, S));
}


public static void main (String[] args) { Chrono timer = new Chrono();
Inventory system = new Inventory (100.0, 2.0, 0.1, 10.0, 1.0, 0.95); system.simulateRuns (500, 2000, 80, 200);
system.statProfit.setConfidenceIntervalStudent();
System.out.println (system.statProfit.report (0.9, 3));
System.out.println ("Total CPU time: " + timer.format());
}
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]