G4-CPU ziemlich langsam?!

-Nuke- schrieb:
Wird doch oben auch nicht anders gemacht mit erg*=x;

Und so etwas rekursives lässt sich nicht parallelisieren. Probier es mal.

-Nuke- schrieb:
Jedoch wird erg unten noch beschnitten. Aber ich habe im Altivec-Tutorial gelesen das Apple in der VecLib noch Altivec-Derivate für pow, sin, cos, usw. hat.
Vielleicht sollte man sich da noch mal umgucken?

Solltest du mal Bedarf an besonders schnellen Versionen dieser Funktionen haben: Ich habe vor einiger Zeit inline-Varianten davon geschrieben, die auf Minimax/Tschebischeff-Approximation beruhen. Sie erfüllen nicht volle IEEE-Genauigkeit, sind jedoch sicher 20mal schneller als die von Apple.
 
Zuletzt bearbeitet von einem Moderator:
Naja. Wie oben ja schon mal gesagt.

Es liegt wohl wirklich an den pow und log10 Funktionen vom System aus und hat anscheinend nicht so viel mit dem Prozessor zu tun...

...und außerdem war ja von Anfang an klar das ein G4 1Ghz nicht schneller als ein AXP 1600+ ist, oder? *ggg*

pow und log10 brauche ich eigentlich so gut wie nie! *ggg*
 
Noch mal ne kleine "Idee".

Ich habe das Ganze mal in Java versucht, leider bin ich nicht weit gekommen, da ich mit Java gerade erst anfange.

Kann es da mal einer Probieren? Vielleicht hat Java ja intelligentere Bibliotheken.

Es geht dabei um die Version mit log10 und pow. Die andere ist ja geschummelt. ;)
 
Hallo,

Also ich würde euch auch unbedingt mal empfehlen den VisualAge C/C++ Compiler zu verwenden. Den gibt es für OS X. Ich hab den mal ausprobiert. Wirkt ähnlich wie Intels Compiler. Bringt nochmal nen spührbaren Schub.
 
Also Java ist langsamer. Braucht rund eine Minute.

In C braucht es bei meinem G4 1,25 Ghz 31 Sekunden.

Ich spiele gerade ein bisschen mit Altivec rum, aber habe noch Probleme bei der pow-Funktion. Die Altivec-Interne rechnet nur 2^vector. Das bringt mir aber nix da ich 10^vector brauche.

Wenn ich Apples Bibliotheken einbinden will, dann gibt´s Linker-Fehler.... *grummel*
 
Logarithmen

Logarithmen kannst du ineinander umrechnen.

Es gilt

log_b(x) = ln(x)/ln(b) ,

wobei ln() den natürlichen Logarithmus zur Basis e (in C/Java ist das der log()) bezeichnet und log_b() den Logarithmus zu einer Basis b. Hast du nur log2() zur Hand, kannst du diese Identität nochmals anwenden, es gilt also

log_b(x) = ln(x)/ln(b) = log2(x)/ln(2)*ln(2)/log2(b) = log2(x)/log2(b)

Um also log10(x) zu berechnen, muss du vorher nur ln(10) oder log2(10) ausrechnen. Falls du die Operation mehrfach brauchst, berechnest du am besten vorher einmal (z.B. per Taschenrechner) den Kehrwert 1/ln(10)=.4342944819 und multiplizierst später damit, denn Divisionen sind teuer.

log10(x) = (1/ln(10))*ln(x) = .4342944819*ln(x)= (1/log2(10))*log2(x) = .3010299957*log2(x)
 
Zuletzt bearbeitet:
-Nuke- schrieb:
Wenn ich Apples Bibliotheken einbinden will, dann gibt´s Linker-Fehler.... *grummel*

Hast du gegen die vecLib gelinkt? Findest du in /System/Library/Frameworks/.

Das AltiVec-interne vec_expte ist übrigens abartig ungenau, ist aber auch gewaltig viel schneller.
 
Zuletzt bearbeitet:
Hi.

Danke, schonmal, aber das war nicht mein Problem. ;)

Das mit dem Logarithmus habe ich schon vorher herrausgefunden, als ich den Java-Port gemacht habe.

Ich habe jetzt Probleme beim Potenzieren.

Ich muss ja erg/=pow(10,log); igendwie portieren. log ist hier der logarithmus.

Bisher sieht es so aus:

erg=vec_madd(vec_re(erg),<hier fehlt das pow>,nullvec);

Ungenau wird es sicher da es alles ja "nur" 32bit Floats sind.

Wie linke ich das Framework hinzu? Ich habe -framework vecLib angefügt.
 
-Nuke- schrieb:
Ich muss ja erg/=pow(10,log); igendwie portieren. log ist hier der logarithmus.

Bisher sieht es so aus:

erg=vec_madd(vec_re(erg),<hier fehlt das pow>,nullvec);

Probier mal so etwas in der Art (ungetestet...)

Code:
const vector float _0 = (vector float)(0),
                   _10= (vector float)(10),
                   mrLn10 = (vector float)(-.4342944819f);
        
// ...
const vector signed int lg = vec_cts(vec_madd(vlogf(erg),mrLn10,_0),0);     
// ...
erg = vec_madd(erg,vipowf(_10,lg),_0);

Durch das Multiplizieren mit mrLn10=-log(10) sparst du dir die Division, da 1/pow(10,x) = pow(10,-x).


Dass du vec_cts für die Ganzzahl-Rundung brauchst, hattest du herausgefunden? Ein einfacher type-cast auf Integer hat in AltiVec nicht die Wirkung, die du vielleicht erwarten würdest.

-Nuke- schrieb:
Ungenau wird es sicher da es alles ja "nur" 32bit Floats sind.

Die "estimate"-Funktionen in Altivec sind noch erheblich ungenauer als die Floatgenauigkeit. Manche (vec_re, vec_rsqrt) lassen sich aber als erste Näherung einer Newton-Raphson-Näherung verwenden, dann sind sie sehr brauchbar.
Tut man das nicht, wird nach einigen Iterationen das Ergebnis nicht mehr viel mit dem Korrekten zu tun haben, schätze ich.
Ich würde in einem ersten Versuch die Apple-vecLib-Funktionen verwenden.

-Nuke- schrieb:
Wie linke ich das Framework hinzu? Ich habe -framework vecLib angefügt.

Wähle in der Projekt-Baumstruktur (links) den Ordner "Frameworks" an und wähle dann den Menüpunkt "Project -> Add Frameworks...". Dann wählst du /System/Library/Frameworks/vecLib.framework.
 
Hi.

OK. Danke erst mal.

Ich habe es bisher über das Terminal gemacht, aber wenn ich wieder zu Hause bin (gegen 17 Uhr) werde ich es mal mit XCode probieren. :)

Mal sehen. Ich hoffe das funktioniert alles so wie ich mir das denke. *ggg*

Bin mal gespannt wie schnell es sein wird, wenn es fertig ist. Ich hoffe es wird mal fertig. ;)

Aber so genau muss das Ergebnis ja gar nicht sein. Es wird ja eh mit 10^xxx angegeben.
 
@Nuke: Könntest Du den Source dann posten,gg ?? Altivec interessiert mich brennend, finde nur nicht die Zeit mich einzuarbeiten :S
 
Ihr werdet von der Geschwindigkeit einer AltiVec-Version enttäuscht sein... AltiVec ist bei diesem Verfahren fehl am Platz.

Es wird auch schwierig sein, etwas schnelleres als das hier (ohne AltiVec) zu finden:

Code:
int main (int argc, char * const argv[])
{        
    long    n = 1, ergexp = 0;
    int     starttime = 0, endtime = 0, x=1;
    
    printf("Geben Sie die Zahl ein dessen Fakultaet bestimmt werden soll: ");
    do
    {
        scanf("%ld", &n);
    }
    while(n<0);

    starttime=(int)time(NULL);
    
    union { float f; int i; } erg;
    erg.f = 1.;
    
    for(x=1; x<=n; x++)
    {
        erg.f *= x;
        ergexp += ((0x7f800000 & erg.i)>>23)-127;
        erg.i = (erg.i & 0x007fffff) | (127 << 23);
    }
            
    double e10 = ergexp/log2(10.);
    ergexp = int(e10);
    erg.f *= pow(10.,(e10-ergexp));
    
    if (erg.f>=10.)
    {
        ergexp++;
        erg.f /= 10.;
    }
    
    endtime=(int)time(NULL);
    printf("\n Das Ergebnis lautet: %f*10^%ld\n", erg.f, ergexp);
    printf("Die Berechnung hat %i Sekunden benoetigt\n", (endtime-starttime) );
    return 0;
}
 
Hey, lass mir doch den Spaß... ;)

Ich weiß sonst nicht was ich programmieren sollte.

Ich habe auch mitbekommen das die G4 keine mathematischen Hochleistungsrechner sind. In einem anderen Forum geht es um 9^(9^9).

Dort ist der G4 auch nicht gerade schnell am rechnen.

Wie lange braucht denn deine neue Routine?
 
Hi.

Ich geb´s auf. ;) Ich kriege es nicht hin.

Am Ende kommt nur Käse bei raus.

Ich glaube zwar immer noch, das man dazu eine schnelle Altivec-Version schreiben könnte durch Verwendung von Parallel-Multiplikation (weil durch das Verfahren oben wird alles 4 mal errechnet, also 3/4 Altivec-Leistung verbraten), aber naja...

Vielleicht später noch mal versuchen.
 
Na gut, das hatte mich ja doch gewurmt... :D

Man kann es parallelisieren, vielleicht hattest du dir das ja so ähnlich gedacht.

Vorsicht... quick'n'dirty-Schweinecode :eek:

Code:
int main (int argc, char * const argv[])
{        
    int    n = 1;
    
    printf("Geben Sie die Zahl ein dessen Fakultaet bestimmt werden soll: ");
    do
    {
        scanf("%ld", &n);
    }
    while(n<0);

    int starttime=(int)time(NULL);
    
    const vector bool int MASK = (vector bool int)(0x7f800000);
    vector float ergv = (vector float)(1);
    vector signed int ergexpv = (vector signed int)(0);
    vector float xv = (vector float)(1,2,3,4);
    
    for(int x=3; x<n; x+=4)
    {
        ergv = vec_madd(ergv,xv,(vector float)(-0.f));
        ergexpv = vec_add(ergexpv,vec_sub(vec_sr(vec_and((vector signed int)ergv,MASK),(vector unsigned int)(23)),(vector signed int)(127)));
        ergv = (vector float)vec_sel((vector signed int)ergv,(vector signed int)(0x3f800000),MASK);
        xv = vec_add(xv,(vector float)(4));
    }
    
    union { float f[4]; vector float v; } ergu;
    union { int i[4]; vector signed int v; } ergexpu;
    
    ergu.v = ergv;
    ergexpu.v = ergexpv;
    
    double erg = ergu.f[0]*ergu.f[1]*ergu.f[2]*ergu.f[3];
    int ergexp = ergexpu.i[0]+ergexpu.i[1]+ergexpu.i[2]+ergexpu.i[3];
    
    double e10 = double(ergexp)/log2(10.);
    ergexp = int(e10);
    erg *= pow(10.,(e10-ergexp));
    
    if (erg>=10.)
    {
        ergexp++;
        erg /= 10.;
    }
    
    for(int x=n-n%4+1; x<=n; x++)
    {
        erg*=x;
        const int lg = (int)log10(erg);
        ergexp += lg;
        erg /= pow(10.,lg);
    }
    
    int endtime=(int)time(NULL);
    
    printf("\n Das Ergebnis lautet: %f*10^%ld\n", erg, ergexp);
    printf("Die Berechnung hat %i Sekunden benoetigt\n", (endtime-starttime) );
    return 0;

}

Aber SCHNELL ist es, hehe. banana So schnell, dass es schon sinnlos ist, weil für Inputs kleiner als etwa 30.000.000 die Antwort einfach sofort da ist und für größere Zahlen die Genauigkeit der Altivec-Floats (32-Bit) nicht ausreicht.
 
Zuletzt bearbeitet:
Na jetzt haste aber die Katze aus dem Sack gelassen =) Hervorragend !!! pepp Welche "Includes" hast Du vorgenommen ? Oder haste die Frameworks genommen ?
 
Hi.

Ja, genauso habe ich mir das gedacht. *ggg* Zumindest denke ich mir das. ;)

Bin mal gespannt wann Altivec2 mit 256bit raus kommt. ;)
 
Winn schrieb:
Welche "Includes" hast Du vorgenommen ? Oder haste die Frameworks genommen ?

Nee, einfach die gleichen Includes wie im Originalprogramm oben. Keine Frameworks.

Code:
#include <stdio.h>
#include <math.h>
#include <time.h>
 
Man muss in XCode einfach nur die Alitvec-Extensions aktivieren (Projekt->Get Info), oder mit der Option -faltivec im Terminal kompilieren.
 
also... ich habe unter anderem ein G3 500mhz ibook mit 768mb ram....
und das kann beim normalen arbeiten locker mit einem pentium 1ghz notebook mithalten....

mein g5 hängt auch meine zweikommairgendwas-windowskiste ab, aber sobald ich was rendern will, sieht der g5 arm aus.

ich meine, ja was meine ich eigentlich. ach ja, man kanns halt nicht 1:1 vergleichen. oder 1:1.5... oder wie auch immer.

zum rendern und berechnen muss man keinen mac kaufen.
 
Zurück
Oben Unten