sin und cos bei hohen Werten extrem langsam

  • Themenstarter wissenhungriger Gast
  • Beginndatum
Status
Nicht offen für weitere Antworten.
W

wissenhungriger Gast

Gast
Hi, ich bin gerade am durchtesten mehrerer Sprachen um ein Gefühl dafür zu bekommen. Ich habe testweise (weil das so in der Art bald auf mich zukommen wird) einen kleinen unrepäsentativen Benchmarktest durchgeführt.

So sehen am Ende auf meiner alten Möhre (winxxppro svp 1GBRam Pentium 4 2.66 MHz) die Ergebnisse aus:

Delphi: 8,6 Sekunden (erster Durchlauf 10Sek)
Java 1.6: 80 Sekunden!! (erstellt mit der netbeans 5.5.1 IDE)
c# : 9 Sekunden
purebasic: 8 Sekunden
Blitzmax: 11 Sekunden

so sieht der Java-Code aus, zumindest der wichtige Algo-Teil:

Getestet habe ich mit 10000 (zehntausend) Clients.

Code:
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        long Anzahl, Iterationen;
        double Sekunden, Minuten, Stunden, DauerMsec;
        long EndTime, NewTime;
        double x=0,y=0,z=0;
            

            EndTime = System.currentTimeMillis();
            Anzahl = Long.parseLong(jTextField1.getText());
            Iterationen = ((Anzahl-1)*Anzahl/2);
            jTextField2.setText(Long.toString(Iterationen));
            jTextField2.repaint();
            jTextField3.setText( "... am rechnen ...");
            jTextField3.repaint();

            for (long i = 0; i < Iterationen; i++)
            {
                y = Math.sin(i);
                x = Math.cos(y);
                z = x * y;
            }
            NewTime = System.currentTimeMillis();
            DauerMsec = (NewTime -EndTime);
            jTextField3.setText(Double.toString(DauerMsec));
            jTextField4.setText(Double.toString(DauerMsec/1000));
            jTextField5.setText(Double.toString(DauerMsec/1000/60));
            jTextField6.setText(Double.toString(DauerMsec/1000/60/60));
            jTextField7.setText(Double.toString(z));
    }

Meine Frage ist jetzt, warum dauert es mit Java sooo lange? Je größer i wird, desto länger braucht es.
Habe ich einen Fehler gemacht? Wie kann man sin und cos optimieren, kann ich für die langsamen Berechnungen auf c oder c++ ausweichen?

Im Endeffekt, soll das Teil sein eines Programms, das auf einen Server laufen soll. Die Aufgabenverteilung wird sein 1. viele sin/cos Berechnungen 2. viele Pakete an vielen Clients schicken 3. Datenbankzugriff.

Und bitte keine Flames oder so was, nur nackte Aufklärung, Java gefällt mir so oder so, auch wenn ich momentan den Weg über Processing gehe und pur Java da einbaue wo ich es brauche.

Danke!

Phil
 
W

wissenhungriger Gast

Gast
Edit: habs nochmal ausgeführt, braucht sogar 88 Sekunden. Habe mal beim compilieren -server angegeben , hat aber nichts gebracht.
 
W

wissenhungriger Gast

Gast
Edit 3 ;)

Hab da noch was weiter geforscht und raus gefunden, dass wohl Java am besten ist bei den Berechnungen zwischen-PI/4 und +Pi/4, also ich flugs den Code geändert und Zack nur noch 9 Sekunden, na das ist doch anehmbar, auch wenn ich dann alles in 45 Grad Teile unterteilen muss. Oder gibts da noch bessere Lösungen?? Sollte wohl endlich schlafen gehn, muss um sieben raus ;)

Code:
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        long Anzahl, Iterationen;
        double Sekunden, Minuten, Stunden, DauerMsec;
        long EndTime, NewTime;
        double x=0,y=0,z=0;
        double jo1 = -1*Math.PI/4;
        double jo2 = Math.PI/4;
        

            EndTime = System.currentTimeMillis();
            Anzahl = Long.parseLong(jTextField1.getText());
            Iterationen = ((Anzahl-1)*Anzahl/2);
            jTextField2.setText(Long.toString(Iterationen));
            jTextField2.repaint();
            jTextField3.setText( "... am rechnen ...");
            jTextField3.repaint();
            double jo3 = 2*jo2/Iterationen;
            double j=jo1;
            for (long i = 0; i < Iterationen; i++)
            {
                y = Math.sin(j);
                x = Math.cos(j);
                z = x * y;
                j=j+jo3;
            }
            NewTime = System.currentTimeMillis();
            DauerMsec = (NewTime -EndTime);
            jTextField3.setText(Double.toString(DauerMsec));
            jTextField4.setText(Double.toString(DauerMsec/1000));
            jTextField5.setText(Double.toString(DauerMsec/1000/60));
            jTextField6.setText(Double.toString(DauerMsec/1000/60/60));
            jTextField7.setText(Double.toString(z));
    }
 
S

SlaterB

Gast
vielleicht teste ich das heute auch noch mal,
ein Hinweis vorweg:
die Anzeige
jTextField2.setText(Long.toString(Iterationen));
jTextField2.repaint();
jTextField3.setText( "... am rechnen ...");
jTextField3.repaint();

dürfte nicht klappen oder doch?
normalerweise blockiert die GUI bis zum Ende der actionPerformed() falls du die nicht bereits in einen eigenen Thread gelegt hast,
das wäre nämlich die Standardlösung
 
S

SlaterB

Gast
ja, das scheint sehr deutlich,
ich habe das ganze mal in ein normales main-Programm gesteckt

Code:
public class Test2
{

    public static void main(String[] args)
    {
        long time = 0;
        int number = 10000000;
        double step = (Math.PI / 4.) / number;

        time = System.currentTimeMillis();
        for (long i = 0; i < number; i++)
        {
            Math.sin(i);
        }
        System.out.println("time : " + (System.currentTimeMillis() - time));

        time = System.currentTimeMillis();
        for (long i = 0; i < number; i++)
        {
            double a = (i / number) * step;
            Math.sin(a);
        }
        System.out.println("time : " + (System.currentTimeMillis() - time));


        for (int i = 0; i < 11; i++)
        {
            double a = 0;
            time = System.currentTimeMillis();
            for (long j = 0; j < number; j++)
            {
                a += step;
                Math.sin(a);
            }
            System.out.println("time : " + (System.currentTimeMillis() - time + ", step: " + step + ", max: " + a));
            step *= 10;
        }


    }

}

Ausgabe:
time : 10949
time : 1205
time : 782, step: 7.853981633974483E-8, max: 0.785398163255418
time : 1689, step: 7.853981633974483E-7, max: 7.853981633943045
time : 1971, step: 7.853981633974484E-6, max: 78.53981634042253
time : 1798, step: 7.853981633974484E-5, max: 785.398163230516
time : 1799, step: 7.853981633974484E-4, max: 7853.981633281307
time : 1940, step: 0.007853981633974483, max: 78539.8163257414
time : 2080, step: 0.07853981633974483, max: 785398.1632299493
time : 10668, step: 0.7853981633974483, max: 7853981.6358696185
time : 11951, step: 7.853981633974483, max: 7.853981634106919E7
time : 12138, step: 78.53981633974483, max: 7.853981634695207E8
time : 12279, step: 785.3981633974483, max: 7.853981635477473E9


die Umrechung von int nach double im Programm ist kein großer Aufwand (zweiter Test),

interessant ist die Untersuchung mit verschiedenen step-Größen,
muss gar nicht im Bereich von PI verlaufen, auch bis 10000fach darüber geht's noch einigermaßen,
dann bei einer 10er-Potenz auf einmal ein großer Bruch in der Laufzeit,
darüber wiederum egal, was das wohl soll.. ;)
 
W

wissenhungriger Gast

Gast
hatte die Info aus hier: forums.java.net/jive/message.jspa?messageID=35756

Hi,
I'm a JVM engineer for Sun and for Mustang I worked on improving trig and transcendental performance. Right now SIN/COS/TAN/LN/LN10/SQRT/ABS are all intrinsified to call directly to hardware. Try a new Mustang build and see what kind of performance improvements you're seeing. Also for trig functions, the Intel hardware is extremely fast for -pi/4 to +pi/4 but slows down outside of these ranges (due to argument reduction). If you can keep your values between those ranges you should see a nice improvement as well.


ich habe jetzt die neue Version in BlitzMax ausprobiert und siehe...Zeit bleibt gleich ???:L da ist jetzt sogar Java noch schneller, das isn Ding wa? :applaus:

Die Kunst ist wirklich heraus zu finden wie man was optimieren kann.

@SlaterB, hast recht, habe das so wie in c# geschrieben und da geht das :) Ich habe bisher noch nicht viel mit Java gemacht, es dauerte mir einfach zu lange, bis ich was grafisches auf die Beine gestellt hatte, aber jetzt mit Processing macht das richtig Spaß, Java in verdauungsgerechten Scheiben quasi :D

Aber ich werde das mit dem Threading mal angehen ^^
 
W

wissenhungriger Gast

Gast
ohne jetzt irgend etwas andeuten zu wollen aber ich habe mal eben den code nach Processing rüber geholt...
Ich hoffe ihr sitzt alle ... 8,5 Sekunden!!!!! und somit so schnell wie Delphi und purebasic, irre! und das von ehemals 90 Sekunden :autsch:

Ach ja hier der Code aber ist ja klar, da ja auch Java mit der Processing Api. Mensch ist das geil, da lohnt sich ja das Kopf zerbrechen über Auslagerung in C oder Assembler gar nicht :bae:
Code:
/*

  Iterationen BenchmarkTest (2007/08/19)

*/

void draw(){
long anzahl = 10000;
long iterationen = 0;
double DauerMsec = 0;
double x=0,y=0,z=0;
long altZeit,neuZeit;
double jo1 = -1*Math.PI/4;
double jo2 = Math.PI/4;
iterationen = ((anzahl-1)*anzahl/2);
// String sf = nf(iterationen,3,5);
println(String.valueOf(iterationen));
double jo3 = 2*jo2/iterationen;
double j=jo1; 
altZeit = millis();
for (long i=0;i<=iterationen;i++)
{
                y = Math.sin(j);
                x = Math.cos(j);
                z = x * y;
                j=j+jo3; 
}
neuZeit = millis();
DauerMsec = neuZeit-altZeit;
println("Zeit in Millis  : " + String.valueOf(DauerMsec));
println("Zeit in Sekunden: " + String.valueOf(DauerMsec/1000));
exit();
}
 

byte

Top Contributor
sin() und cos() sind im übrigen native Methoden. Es ist also an dieser Stelle nicht Java selbst so schnell. ;)
 
S

SlaterB

Gast
Java ist Schuld, Windoof dran zu lassen ;)
(edit: habe ' Es ist also an dieser Stelle nicht Java selbst so langsam' gelesen)
 
W

wissenhungriger Gast

Gast
hmmm, mag ja alles sein, aber BlitzMax kompiliert mit MinGW, selbst eine Auslagerung der sin und cos Funktionen in reinem C mit der neuesten MinGW Version hat nichts gebracht, also muss Java auch eine 'Teilschuld' an diesem netten Resultat haben.
 

byte

Top Contributor
Offenbar hat Sun einfach nur ziemlich schnelle Algorithmen geschrieben, aber die sind halt nicht in Java-Code implementiert, sondern es wird nativer Code aufgerufen.
 
G

Gast

Gast
übrigens, nette sache, wenn man viele sin/cos dinger für ganzzahlige Gradwerte braucht: einfach ein final double[360] Array (als Feld) erstellen und jeden index mit dem sinus/cosinus Wert des entsprechenden indexes speichern. das ergibt einen gewaltigen performanceboost!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Test mit Werten aus der .properties Allgemeine Java-Themen 4
Zrebna Random Number - Generische Formel zwischen zwei INKLUSIVEN Werten Allgemeine Java-Themen 16
O Variablen Addition von Double-Werten ergibt seltsame 0.9999999 Zahlen Allgemeine Java-Themen 2
S @Value mit bestimmt Werten, sonst default Allgemeine Java-Themen 42
Z Array mit unterschiedlichen Werten Allgemeine Java-Themen 1
B Verteilungs-/Vergabe-Algorithmus mit abhängigen Score-Werten Allgemeine Java-Themen 3
L einfache Verzinsung mit for-Schleife & Ausschluss von Werten beim Einlesen Allgemeine Java-Themen 5
T Sechsecke, erkennen von bestimmten Werten Allgemeine Java-Themen 9
I Datentypen Mögliche Auswahl an Werten Allgemeine Java-Themen 4
I 2D-Grafik Polygon mit Double Werten zeichnen Allgemeine Java-Themen 4
S Baum mit vordefinierten Werten befüllen Allgemeine Java-Themen 2
M Problem mit return-werten Allgemeine Java-Themen 35
O Problem bei der Umwandlung von Hex-Werten Allgemeine Java-Themen 5
T Wurfweitenberechnung: X-Werte bei extremen Werten falsch. Allgemeine Java-Themen 15
A Problem bei Übergabe von Werten in ein double Array. Allgemeine Java-Themen 21
N Array mit null Werten filtern Allgemeine Java-Themen 5
MQue zwischen Class zum speichern von Werten Allgemeine Java-Themen 4
S Problem beim Einlesen von byte-werten aus datei Allgemeine Java-Themen 2
G JComboBox mit Werten aus einer Access Datenbank füllen Allgemeine Java-Themen 18
G Einfügen von Werten aus TXT-Datei in ein Array !?! Allgemeine Java-Themen 9
E JavaFX RMI extrem langsam wenn Server nicht läuft Allgemeine Java-Themen 5
E mit extrem langen Zahlen (als Zeichneketten) arbeiten Allgemeine Java-Themen 4
N Liste mit Map abgleichen extrem langsam Allgemeine Java-Themen 6
C Darstellung der Liste bei vielen Daten extrem langsam Allgemeine Java-Themen 11
F Kleingerechnete Bilder extrem dunkel Allgemeine Java-Themen 2
A testen ob Primzahl dauert bei größeren zahlen extrem lange Allgemeine Java-Themen 8
P rechnen mit extrem grossen zahlen Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben