memcpy schneller als Schleife?



  • template metaprogrammierung



  • Original erstellt von MaSTaH:
    @Winn
    Hä, templates haben mit Schleifen doch nicht das geringste zu tun.

    doch, doch.
    man kann nen TinyVector<typename T,size_t SIZE>{T data[SIZE]... so implementieren, daß der Copy-Konstruktor ne normale for-Schleife nimmt, daß er memcpy nimmt, daß er duff's device nimmt, oder daß er per templates ne Schleife komplett unrolled. Und letzteres ist für Blitz++ typisch.



  • @Mastah

    Wenn ich das wußte, dann würd ich Dir mehr dazu posten, mich hatte ein Kumpel auf die Blitz++ Library gebracht, weil ich Performance brauchte, dann laß ich von den Templates und rekursiven Handlings... da gingen bei mir erstmal die Nackenhaare hoch, weil Rekusionen sind ja vielleicht fein, aber sau lahm, einfache Iterationen bieten sich dort besser an, aber diese Templates scheinen Dampf zumachen... der Kernpunkt der damit ausgestochen wird ist, daß der Compiler nur Pointer und Adressen sieht, also keine Ahnung vom eigentlichen Ablauf hat oder sagen wir von einem sinnigen Ablauf. Compiler die auf die Semantik achten und entsprechend der Programmlogik compilieren sind wohl gescheitert. Der Kai C++ Compiler wurde von Intel aufgekauft, er war das beste Stück in diesem Bereich. Mit den Templates läßt sich aber wohl diese Semantische Lücke schließen...

    Schau dir die Blitz++ Library mal an, sie ist Open Source und steht unter GNU. Wollte jetzt demnächst mal ein Test Programm schreiben, werde mich dann wieder zurückmelden...

    Winn



  • @volkard
    Rekursion mit Templates kann ich mir vorstellen. Oder meinst du was anderes? Werd mir die Blitz-Library mal angucken.



  • Original erstellt von MaSTaH:
    @volkard
    Rekursion mit Templates kann ich mir vorstellen. Oder meinst du was anderes? Werd mir die Blitz-Library mal angucken.

    doch, genau das meine ich.



  • Original erstellt von Shade Of Mine:
    **
    der compiler kann nämlich zaubern - der macht mal ein memcpy so rum und woanders macht ers andersrum, also der weiß schon wie er zu optimieren hat.
    **

    Das mit dem mal so und mal so rum hat nen andren Grund, je nachdem ob man:

    char array[500];
    char* dest = &array[110];
    char* src = &array[100];
    memcpy(dest, src, 100);
    // oder
    char* dest = &array[100];
    char* src = &array[110];
    memcpy(dest, src, 100);
    

    macht würde, wenn memcpy nur von links nach rechts bzw von rechts nach links kopieren könnte, ein falsches Ergebnis kommen, weil er das bereits kopierte nochmal kopiert wird.

    [ Dieser Beitrag wurde am 14.05.2003 um 11:42 Uhr von dreaddy editiert. ]



  • dafür gibts memmove.
    mit sorum&andersrum war wohl eher gemeint, daß er aus
    (ich nehme int*a an)

    memcpy(a,b,0) ein {} macht, aus
    memcpy(a,b,4} ein MOV, aus
    memcpy(a,b,40) ein REPNE MOV und aus
    memcpy(a,b,n) ein CALL _memcpy (oder doch nur ein REPNE MOV, wenn er weiß, daß n klein ist?) und aus
    {int* a=new int[100];memcpy(a,a,400);delete a;} ein {}.



  • Hey nochmal,

    also die Blitz Lib ist schon eine feine Sache, allerdings für meine Ansprüche war sie zu langsam. Leider 😞 Anbei der Quellcode für eine Template For Schleife und If Abfrage, gefunden unter [url] http://home.t-online.de/home/Ulrich.Eisenecker/meta.htm [/url]...

    Gruß Winn

    HEADER

    #ifndef _METACTRL
    #define _METACTRL
    
    namespace metactrl
    {       
    
    // IF<>
    
            namespace intimate
            {
                    struct SelectThen 
                    {       template<class Then, class Else>
                            struct Result
                            {       typedef Then RET;
                            };
                    }; // end SelectThen
    
                    struct SelectElse
                    {       template<class Then, class Else>
                            struct Result
                            {       typedef Else RET;
                            };
                    }; // end SelectElse
    
                    template<bool Condition>
                    struct Selector
                    {       typedef SelectThen RET;
                    }; // end Selector
    
                    template<>
                    struct Selector<false>
                    {       typedef SelectElse RET;
                    }; // end Selector<false>
            } // end namespace private
    
            template<bool Condition, class Then, class Else>
            struct IF
            {       typedef intimate::Selector<Condition>::RET select;
                    typedef select::Result<Then,Else>::RET RET;
            }; // IF
         
    // FOR<>, comparators // for convenience
    
            struct Equal
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval == rval};
                    };
            }; // end Equal
    
            struct NotEqual
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval != rval};
                    };
            }; // end NotEqual
    
            struct Less
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval < rval};
                    };
            }; // end Less
    
            struct LessEqual
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval <= rval};
                    };
            }; // end LessEqual
    
            struct Greater
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval > rval};
                    };
            }; // end Greater
    
            struct GreaterEqual
            {       template <int lval, int rval>
                    struct Test
                    {       enum {evaluate = lval >= rval};
                    };
            }; // end GreaterEqual
    
            template <int From,class Compare,int To,int By,class Statement>
            struct FOR
            {       static void EXEC()
                    {       IF <Compare::Test<From,To>::evaluate,
                                    Statement::Code<From>,
                                    intimate::Stop>
                            ::RET::execute();
                            IF <Compare::Test<From,To>::evaluate,
                                    FOR<From+By,Compare,To,By,Statement>,
                                    intimate::Stop>
                            ::RET::EXEC();
                    };
            }; // end FOR
    
    } // end namespace metactrl
    #endif _METACTRL
    

    USING

    // METAXMPL.CPP - Copyright (C) 1998 by 
    // Ulrich W. Eisenecker and 
    // Krzysztof Czarnecki
    // This file demonstrates the usage of the template-metaprogramming
    // control-structures of METACTRL
    
    #include <iostream>
    #include "metactrl"
    
    using namespace std;
    using namespace metactrl; // all meta-controlstructures are in namespace "metactrl"
    
    // stuff for testing IF<>
    
    struct DemoThen
    {       DemoThen()
            {       cout << "DemoThen" << endl;
            }
    };
    
    struct DemoElse
    {       static void execute()
            {       cout << "DemoElse" << endl;
            }
    };
    
    // stuff for testing SWITCH<>
    
    struct A
    {       static void execute()
            {       cout << "A" << endl;
            }
    };
    
    struct B
    {       static void execute()
            {       cout << "B" << endl;
            }
    };
    
    struct C
    {       C()
            {       cout << "C" << endl;
            }
    };
    
    // stuff for testing FOR<>
    
    struct DemoFor
    {       template <int i> // "i" is the loop variable
            struct Code
            {       static void execute()
                    {       cout << i << endl;
                    }
            };
    };
    
    struct DemoNestedFor
    {       template <int i> // "i" is the first loop variable
            struct Code
            {       struct NestedStatement
                    {       template <int j> // "j" is the second loop variable
                            struct Code
                            {       static void execute()
                                    {       cout << i << '|' << j;
                                            if (i == j)
                                            cout << endl;
                                            else cout << '\t';
                                    }
                            };
                    };
                    static void execute()
                    {       FOR<i+1,Less,5,+1,NestedStatement>::EXEC();
                            cout << endl;
                    };
            };
    };
    
    int main()
    {
            // Testing IF<>
            cout << "Testing IF<>" << endl;
            IF<true,DemoThen,DemoElse>::RET if_result;      // declare variable
            IF<false,DemoThen,DemoElse>::RET::execute();    // call class function
    
            // Testing FOR<>
            cout << "Testing FOR<>" << endl;
            FOR<10,Greater,1,-2,DemoFor>::EXEC();             // define it and use it immediately
            // How to nest loops? Here is the answer:
            typedef FOR<0,Less,5,+1,DemoNestedFor> for_loop;  // define it
            for_loop::EXEC();                                 // and use it later
    
            return 0;
    }
    


  • Also ich kann mir nicht helfen. Irgendwie gefällt mir diese Art der Programmierung nicht. Bringt das rein performancetechnisch eigentlich viel?



  • Herkömmliche Methode Du startest das programm und etwas wird berechnet. Templatemetaprogrammierung: Wärend des Compilierens wird bereits einiges berechnet und beim ausführen nurnoch ausgegeben.



  • Herkömmliche Methode: Compilierzeit 2s, Berechnung 10 µs, Ausgabe 100µs
    Template-Meta-Methode: Compilierzeit 2min, Berechnung 0,1 µs, Ausgabe 100µs



  • Also bringts quasi nur was wenn man viel berechnet und wenig ausgibt. Dann dauert das kompilieren aber so lange wie ein Kind zu gebären. Frohes Debuggen 😉 😃



  • @Bashar
    Welche Art von Berechnung hast Du ausgeführt ? Bisher hab ich nur die Blitz++ Lib genutzt, die Template Technik hab ich noch nicht genutzt... zeig mal deinen Testrahmen ?

    Gruß Winn



  • ???



  • meiste zeit brauchen im Normalfall eh die Ausgaben.



  • Am Besten ihr werft alles durcheinander. Dazu eine Packung gefährliches Halbwissen. Guten Appetit.

    *kopfschüttel*



  • Original erstellt von HumeSikkins:
    **Am Besten ihr werft alles durcheinander. Dazu eine Packung gefährliches Halbwissen. Guten Appetit.

    *kopfschüttel***

    Es sind Optionen !! Möglichkeiten, ob sie passen oder nicht... Ein Forum ist stets eine Art Brain Storming, in denen Du bestimmt auch mal gute Lösungen erhalten hast, sonst würdest Du auf Deiner HP nicht erwähnen, daß dieses Forum das beste Deutschsprachige ist ! Oder 🙄

    @Bastah
    Hattest Du die Zeilen nur als extremes Beispiel erwähnt oder hattest Du ein kleines Testprogramm geschrieben ? Hab mir den Stoff erstmal angelesen, aber angewendet halt noch nicht... da meine Diplomarbeit ein "Number Cruncher" wird, wäre es sehr hilfreich zu wissen ?!

    Gruß Winn



  • Original erstellt von Winn:
    @Bastah

    Wen meinst du jetzt? Bashar oder MaSTaH?



  • Original erstellt von Winn:
    @Bashar
    Welche Art von Berechnung hast Du ausgeführt ? Bisher hab ich nur die Blitz++ Lib genutzt, die Template Technik hab ich noch nicht genutzt...

    Ich denke mal er hat geschätzt ;). BTW: Die Blitz-Lib verwendet Templates



  • Jo, weiß ich, hatte mir viel von erhofft, aber war halt nicht schneller...
    schau mal unter [url] http://www.abarnett.demon.co.uk/tutorial.html [/url] besonders der Punkt "Dynamic Loop Unrolling" bzw. "Faster For Loops"

    Gruß Winn


Anmelden zum Antworten