Schleife



  • Hallo!

    // Schleife 5 mal durchlaufen --> Allen Elementen 22 zuweisen
    int *p1, vec[5];
    for(p1=vec, p1<vec+5, ++p1) { *p1=22 }
    
    // Schleife 5 mal durchlaufen --> Allen Elementen 22 zuweisen
    int i, vec[5];
    for(i=0; i<5; ++i) { vec[i]=22 }
    

    Ihr seht hier zwei verschiedene Möglichkeiten alle Elemente von vec auf 22 zu setzen.

    Höre immer wieder das Möglichkeit 1 mit einer "schnelleren Laufzeit" ausgeführt wird, stimmt das? 😕

    Grund soll wohl sein, das der Compiler bei der ersten Konstruktion Konstante Werte schreibt & festlegt, und bei Alternative 2 nicht.



  • wie wärs mit ausprobieren -> clock()



  • kenner der dummköpfe schrieb:

    wie wärs mit ausprobieren -> clock()

    Solche Micro-Unterschiede (wenn überhaupt) zuverlässig zu timen ist gar nicht so einfach. Und 'clock' reicht da mit Sicherheit nicht aus.

    Also erkenn Dich mal selbst und lass Deine klugen Sprüche.



  • mal meinen senf dazu geben #gg
    ich denk das die zeiger variante schneller sein muesste, aber nur extrem wenig

    int *p1, vec[5];
    for(p1=vec, p1<vec+5, ++p1) { *p1=22 }
    

    hier wird ein zeiger auf dem array erstellt, dieser wird auch inkrementiert und direkt zur zuweisung benutzt

    int i, vec[5];
    for(i=0; i<5; ++i) { vec[i]=22 }
    

    hier wird erst eine int variable erstellt, welche inkrementiert wird und dann wird erst zugegriffen

    also ein int ist groesser als ein zeiger
    und bei vec[5] wird, soweit ich das glaub, noch ein zwischenschritt notwendig (differenziert)
    bei nem zeiger kannst du direkt damit arbeiten



  • Das ist doch eigentlich mal ganz interessant. Das muss sich doch irgendwie timen lassen, zumindest wenn man die Schleife verlängert, sagen wir das Feld hätte 10000 Elemente...
    Ich suche schon lange nach einer Möglichkeit sowas einigermaßen genau zu timen.



  • Mr Evil schrieb:

    int *p1, vec[5];
    for(p1=vec, p1<vec+5, ++p1) { *p1=22 }
    

    hier wird ein zeiger auf dem array erstellt, dieser wird auch inkrementiert und direkt zur zuweisung benutzt

    … und außerdem wird für jeden Test eine Addition ausgeführt (die kann man herausziehen, dann erstellt man aber wieder ne Variable).

    also ein int ist groesser als ein zeiger

    Äh?

    #include <iostream>
    
    int main()
    {
        std::cout << sizeof(int) << ' ' << sizeof(int*) << std::endl;
    }
    

    Ergibt auf meinem System:

    $ ./a.out
    4 4
    

    Ich vermute mal, dass die meisten optimierenden Compilern aus solch einem Code so ziemlich das gleiche machen werden.



  • Am einfachsten ist's wohl, das ganze durch den Compiler zu jagen und den rauskommenden Assambler-Code zu vergleichen.

    (aber ich würde mal sagen, die Schleifen müssten etwa gleich schnell sein - von Mikro-Optimierungen des Compilers mal abgesehen)



  • WarMal schrieb:

    Das ist doch eigentlich mal ganz interessant. Das muss sich doch irgendwie timen lassen, zumindest wenn man die Schleife verlängert, sagen wir das Feld hätte 10000 Elemente...

    Wird nichts bringen, zumal ich vermute, dass hier alle möglichen Compiler was anderes draus bauen. Letztendlich müsste man sich den Assembler-Code anschauen.

    Ich suche schon lange nach einer Möglichkeit sowas einigermaßen genau zu timen.

    // timer.hpp
    // Copyright blablablubbblubb
    
    #ifndef MADRAT_SEQAN_TIMER_H
    #define MADRAT_SEQAN_TIMER_H
    
    #include <iostream>
    #include <iomanip>
    
    #ifdef WIN32
    #   include <windows.h>
    #else
    #   error "No compatible platform."
    #endif
    
    namespace madrat { namespace debug {
    
        class Timer {
        public:
            Timer(std::string const& test)
                : m_test(test)
                , m_start(get_ticks())
            { }
    
            ~Timer()
            {
                using namespace std;
                LARGE_INTEGER stop = get_ticks();
                double duration = static_cast<double>(stop.QuadPart - m_start.QuadPart) /
                                  static_cast<double>(m__frequency.QuadPart);
                cerr << m_test << setw(28) << right << setprecision(10) << fixed << duration << 's';
            }
    
        private:
            static LARGE_INTEGER m__frequency;
            static BOOL const m__has_counter;
    
            std::string m_test;
            LARGE_INTEGER m_start;
    
            static LARGE_INTEGER get_ticks()
            {
                LARGE_INTEGER ret;
                ::QueryPerformanceCounter(&ret);
                return ret;
            }
        };
    
        LARGE_INTEGER Timer::m__frequency = LARGE_INTEGER();
        BOOL const Timer::m__has_counter = ::QueryPerformanceFrequency(&Timer::m__frequency);
    
    } }
    
    #endif // !defined(MADRAT_SEQAN_TIMER_H)
    

    /EDIT: ROFL, mir fällt gerade auf, dass ich in einem Posting einen Unix-Compiler verwende und ein Kompilat per "./a.out" starte … und im nächsten Posting einen Windows-spezifischen Code hinklatsche. Na ja. Das eine ist halt Freizeit und das andere Arbeit.



  • Sehr schön,

    das ist zwar eine ganze Menge Windows-API für jemanden, der sich damit nicht auskennt und es ist wohl deshalb auch nicht standard-konform, aber:
    Es funktioniert und man kann den Header ja zum entwickeln einbinden und anschließend wieder rausschmeißen. Dankesehr.

    P.S.
    Ich finde der Code wäre FAQ-geeignet.




Anmelden zum Antworten