Ideen zur Beschleunigung des Codes (Camera Bild einlesen)



  • Nein, im Ursprungscode wird das Bild in drei separate Felder geschrieben. Die Daten sind auch 24 bit weise organisiert.



  • Ja mein gott,..
    dann halt:

    u8* redmemory  = getStartOfRedMemory();
    u8* bluememory = getStartOfBlueMemory();
    u8 greenmemory = getStartOfGreenMemory();  
    
    RGBX* RGBXMemory = getStartOfRGBXMemory();
    
    size_t ColorIndex=0;
    size_t RGBXIndex=0;
    
    for( int i=0; i<number_of_pixels; i++)
    {
      memcpy_s(redmemory  + ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 2,1);
      memcpy_s(bluememory + ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 1,1);
      memcpy_s(greenmemory+ ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 0,1);
    RGBXIndex++;
    ColorIndex++;
    }
    

    grüüße



  • zeusosc schrieb:

    Ja mein gott,..
    dann halt:

    memcpy_s(redmemory  + ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 2,1);
      memcpy_s(bluememory + ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 1,1);
      memcpy_s(greenmemory+ ColorIndex,1,((char*)RGBXMemory + RGBIndex) + 0,1);
    

    memcpy_s braucht man nicht 🙂
    Dann läuft das ganze noch einen Tacken schneller.



  • Die memcpy_s Version ist bei mir deutlich langsamer, die mit memcpy ein Drittel schneller:

    `

    Copying with Mul based address calculation: Time elapsed 11.236s

    Copying with Add based address calculation: Time elapsed 0.313s

    Copying with memcpy_s based address calculation: Time elapsed 4.844s

    Copying with memcpy based address calculation: Time elapsed 0.203s

    `

    Also macht memcpy das Rennen. Hab' ich wieder was gelernt, ich hatte vermutet, dass bei wortweisem Kopieren da kein Unterschied ist. Danke für den Tipp!



  • ogni42 schrieb:

    ...

    Könntest du grad den Code nochmal posten, so langsam verliert man den Überblick wo welche Veränderungen enthalten sind.

    0.2s je Frame ist doch ein wenig langsam.
    uEye cams können doch wohl mehr als 5frames/s?
    Oder ist es die Messung im Debug Modus?



  • Hier nochmal mein Testcode:

    #include <iostream>
    #include <Timer.h>
    
    using std::cout;
    using std::endl;
    
    const int m_size_x = 1024;
    const int m_nSizeX = 1024;
    const int m_nSizeY = 1024;
    
    const int chunkSz = 5*m_nSizeX*m_nSizeY;
    int largeChunk[chunkSz];
    
    char red[chunkSz];
    char green[chunkSz];
    char blue[chunkSz];
    
    // Diese struct muss der organisation eines Pixels im Speicher entsprechen
    struct RGBPixel32
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
        unsigned char x; // unused, 32bit alignment
    };
    
    struct RGBPixel24
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
    };
    
    struct MonoPixel8
    {
        unsigned char g;
    };
    
    struct MonoPixel10Left // left aligned
    {
        unsigned short pad  :    6; // padding bits
        unsigned short g    :   10; // 10bit grey value
    };
    
    struct MonoPixel10Right
    {
        unsigned short g    :   10; // 10bit grey value
        unsigned short pad  :    6; // padding bits
    };
    
    void pixelToRGB(char* pPixelPointer, int  & r, int & g, int & b)
    {
        r = static_cast<int>(*(reinterpret_cast<char*>(pPixelPointer+2)));
        g = static_cast<int>(*(reinterpret_cast<char*>(pPixelPointer+1)));
        b = static_cast<int>(*(reinterpret_cast<char*>(pPixelPointer+0)));
    }
    
    inline int ArrPos(int x, int y)
    {
        // y + height * x
        return (x + m_size_x * y);
    } 
    
    inline void setPixel(int x, int y, int r, int g, int b)
    {
        int pos = ArrPos(x,y);
        red[pos] = r;
        green[pos] = g;
        blue[pos] = b;
    }
    
    void checkPerfMult(void)
    {
        int m_nBytesPerPixel = 4;
        int nPitch = 4;
        void* pMemVoid = (void*)largeChunk;
        char* pPixelPointer;
        for ( int x = 0; x < m_nSizeX; x++ ) 
        {
            for ( int y = 0; y < m_nSizeY; y++ ) 
            {
                // (x*bytes) + (y * sizex)
                int r;
                int g;
                int b;
                long lMemoryPixelOffset = ((long)x * m_nBytesPerPixel) + ((long)y * nPitch );
                pPixelPointer = (reinterpret_cast<char*> (pMemVoid) + (lMemoryPixelOffset)) ;
    
                pixelToRGB(pPixelPointer, r, g, b);
                setPixel(x,y,r,g,b);
            }
        } 
    }
    
    void* getImageStart(void)
    {
        return largeChunk;
    }
    
    void checkPerfAdd(void)
    {
        // jetzt der Zugriff
        RGBPixel32* imageIterator = reinterpret_cast<RGBPixel32*>(getImageStart()); // Hier den Start des Bildes im Speicher bestimmen
        int targetIterator = 0;
        for( int y = 0; y < m_nSizeY; y++ )
        {
            for( int x = 0; x < m_nSizeX; x++ ) // hier wird imageStart immer um ein ganzes Pixel weiter geschoben
            {
    //            setPixel(x, y, imageIterator->r, imageIterator->g, imageIterator->b);
                red[targetIterator] = imageIterator->r;
                green[targetIterator] = imageIterator->g;
                blue[targetIterator] = imageIterator->b;
                imageIterator++;
                targetIterator++;
            }
        } 
    }
    
    char* getStartOfRedMemory()
    {
        return red;
    }
    
    char* getStartOfGreenMemory()
    {
        return green;
    }
    
    char* getStartOfBlueMemory()
    {
        return blue;
    }
    
    RGBPixel32* getStartOfRGBXMemory()
    {
        return reinterpret_cast<RGBPixel32*>(getImageStart());
    }
    
    void checkPerfMemCpy_s()
    {
        char* redmemory  = getStartOfRedMemory();
        char* bluememory = getStartOfBlueMemory();
        char* greenmemory = getStartOfGreenMemory();  
    
        RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    
        size_t ColorIndex=0;
        size_t RGBXIndex=0;
        int  number_of_pixels = m_nSizeX*m_nSizeY;
    
        for( int i=0; i<number_of_pixels; i++)
        {
            memcpy_s(redmemory  + ColorIndex,1,((char*)RGBXMemory + RGBXIndex) + 2,1);
            memcpy_s(bluememory + ColorIndex,1,((char*)RGBXMemory + RGBXIndex) + 1,1);
            memcpy_s(greenmemory+ ColorIndex,1,((char*)RGBXMemory + RGBXIndex) + 0,1);
            RGBXIndex++;
            ColorIndex++;
        } 
    }
    
    void checkPerfMemCpy()
    {
        char* redmemory  = getStartOfRedMemory();
        char* bluememory = getStartOfBlueMemory();
        char* greenmemory = getStartOfGreenMemory();  
    
        RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    
        size_t ColorIndex=0;
        size_t RGBXIndex=0;
        int  number_of_pixels = m_nSizeX*m_nSizeY;
    
        for( int i=0; i<number_of_pixels; i++)
        {
            memcpy(redmemory  + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 2,1);
            memcpy(bluememory + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 1,1);
            memcpy(greenmemory+ ColorIndex,((char*)RGBXMemory + RGBXIndex) + 0,1);
            RGBXIndex++;
            ColorIndex++;
        } 
    }
    
    int main( void )
    {
        const int runs = 100;
        {
            cout << "Copying with Mul based address calculation: ";
            Timer t;
            for (int i = 0; i<runs; i++)
            {
                checkPerfMult();
            }
        }
        cout << endl;
        {
            cout << "Copying with Add based address calculation: ";
            Timer t;
            for (int i = 0; i<runs; i++)
            {
                checkPerfAdd();
            }
        }    
        cout << endl;
        {
            cout << "Copying with memcpy_s based address calculation: ";
            Timer t;
            for (int i = 0; i<runs; i++)
            {
                checkPerfMemCpy_s();
            }
        }
        cout << endl;
        {
            cout << "Copying with memcpy based address calculation: ";
            Timer t;
            for (int i = 0; i<runs; i++)
            {
                checkPerfMemCpy();
            }
        }
        cout << endl;
    }
    

    Und hier die Compileroptionen von VisualC++ 2008:
    /O2 /Ob2 /Oi /Ot /GL /I "C:\work\learning\playGroundForCpp\playGroundForCpp" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /Gy /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /errorReport:prompt

    Bitte beachten: Ich teste nur auf einem Laptop mit lahmem Speicher und 1.6GHz CPU

    EDIT: Die Messungen sind mit dem Release Build gemacht.



  • ogni42 schrieb:

    Bitte beachten: Ich teste nur auf einem Laptop mit lahmem Speicher und 1.6GHz CPU

    Achso.. ist es vielleicht ein Mehrkernprozessor?



  • Ja, Core 2 Duo@1,6GHz.



  • 10000 Durchgänge:
    ohne parallel for in Zeile 14: ~4000
    mit pragma #omp parallel for in Zeile 45: ~1300

    Dazu OpenMP Support im Compiler anschalten.

    Skaliert um Faktor 3 bei 4 Prozessoren... ist ein wenig lausig.. aber OpenMP ist halt nicht so besonders.

    Man müsste das Alignment auf 128 bringen, da bietet der Intel Compiler ein wenig bessere Tools.

    Benche mal mit deinen Einstellungen.
    Ich habe timer.h nicht.

    #include <iostream>
    #include <ctime>
    #include <cstdlib>
    #include <cstdio>
    
    int main( void )
    {
    	clock_t start=0,stop=0;
    
    	const int runs = 10000;
    ....
    		cout << "Copying with memcpy based address calculation: ";
    		start=clock();
    		#pragma omp parallel for
    		for (int i = 0; i<runs; i++)
    		{
    			checkPerfMemCpy();
    		}
    		stop = clock();
    ....
    	cout << (float) 1000*(stop-start) / CLOCKS_PER_SEC <<endl;
    }
    


  • Jetzt wird es interessant. Zieht man das OpenMP Pragma in die Kopierroutine, wird auf einmal die non-memcpy Version schneller (1000 Durchläufe):

    `

    Copying with Add based address calculation: Time elapsed 2.984s

    Copying with memcpy based address calculation: Time elapsed 4.641s

    Drücken Sie eine beliebige Taste . . .

    `

    void checkPerfMemCpy()
    {
        char* redmemory  = getStartOfRedMemory();
        char* bluememory = getStartOfBlueMemory();
        char* greenmemory = getStartOfGreenMemory();  
    
        RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    
        size_t ColorIndex=0;
        size_t RGBXIndex=0;
        int  number_of_pixels = m_nSizeX*m_nSizeY;
    
    #pragma omp parallel for
        for( int i=0; i<number_of_pixels; i++)
        {
            memcpy(redmemory  + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 2,1);
            memcpy(bluememory + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 1,1);
            memcpy(greenmemory+ ColorIndex,((char*)RGBXMemory + RGBXIndex) + 0,1);
            RGBXIndex++;
            ColorIndex++;
        } 
    }
    
    void checkPerfAdd(void)
    {
        // jetzt der Zugriff
        RGBPixel32* imageIterator = reinterpret_cast<RGBPixel32*>(getImageStart()); // Hier den Start des Bildes im Speicher bestimmen
        int targetIterator = 0;
    #pragma omp parallel for
        for( int y = 0; y < m_nSizeY; y++ )
        {
            for( int x = 0; x < m_nSizeX; x++ ) // hier wird imageStart immer um ein ganzes Pixel weiter geschoben
            {
    //            setPixel(x, y, imageIterator->r, imageIterator->g, imageIterator->b);
                red[targetIterator] = imageIterator->r;
                green[targetIterator] = imageIterator->g;
                blue[targetIterator] = imageIterator->b;
                imageIterator++;
                targetIterator++;
            }
        } 
    }
    

    Dafür habe ich jetzt keine Erklärung, höchstens eine Vermutung: OpenMP packt Schleifendurchläufe in parallele Threads. Dabei könnten sich bei der memcpy-Version die Cores beim Zugriff auf die Caches in die Quere kommen. Das ist mit Sicherheit aber sehr abhängig davon, auf welchem Zielsystem das Programm läuft.

    Dennoch, von ursprünglich 100ms Laufzeit/Bild sind wir jetzt bei unter 5ms/Bild. Das ist doch schon was 😃

    EDIT:
    Fazit: Die nicht parallelisierte memcpy Version ist die Beste.



  • ogni42 schrieb:

    [/cpp]

    Dafür habe ich jetzt keine Erklärung, höchstens eine Vermutung: OpenMP packt Schleifendurchläufe in parallele Threads. Dabei könnten sich bei der memcpy-Version die Cores beim Zugriff auf die Caches in die Quere kommen. Das ist mit Sicherheit aber sehr abhängig davon, auf welchem Zielsystem das Programm läuft.

    Dennoch, von ursprünglich 100ms Laufzeit/Bild sind wir jetzt bei unter 5ms/Bild. Das ist doch schon was 😃

    Warte mal... in der Funktion musst du ein wenig aufpassen dass zwei Threads nicht gleichzeitig auf eine Adresse zugreifen.. das geht ein wenig anders. Es ist langsamer weil OpenMP die Zugriffe koordinieren muss.

    Ich dachte du rufst X-Mal diese Funktion auf und holst dir damit mehrere Bilder heraus. Deswegen habe ich das omp vor die funktion gemacht.

    Wie genau läuft jetzt der Vorgang ab??

    Wenn du es wie an der Stelle 13 und 29 (dein Codeposting) brauchst, dann muss es ganz anders angegangen werden.

    Dann wird das Bild als RAM-Block in n-Blöcke aufgeteilt wobei jeder Block von einem Thread abgegrast wird.



  • Der Aufruf (x-Mal, x=100 oder 1000) ist nur, damit man mit clock() vernünftig messen kann. Um die Funktion auszuführen muss die Funktion nur einmal aufgerufen werden.

    Aber ich verstehe, was Du meinst, Die Zugriffe müssen synchronisiert werden, weil sonst das Inkrementieren der Zähler zu indizierungsfehlern führen kann. Ich schlage mal in der Hilfe nach und baue das ein.

    Oder muss ich sonst noch was beachten?

    EDIT: Ich fürchte, dass ich hier etwas Hilfe von einem erfahreneren OpenMP-Nutzer brauche: Die Indexvariablen werden ja von den Threads geteilt und somit ist das in der Form IMHO nicht OpenMParallelisierbar. Meine Idee wäre, für eine feste Anzahl Threads (das geht mit OpenMP) den Code umzuschreibe, so dass bei n Thredas je Thread 1/n-tel des Bildes derart bearbeitet wird, dass (n=2) Thread0 die obere Hälfte und Thread1 die untere Hälfte bearbeitet.

    Wäre das so praktikabel?



  • Jetzt muss ich mal was ganz doofes in die Runde fragen. Ist in diesem Fall:

    memcpy(redmemory  + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 2,1);
    memcpy(bluememory + ColorIndex,((char*)RGBXMemory + RGBXIndex) + 1,1);
    memcpy(greenmemory+ ColorIndex,((char*)RGBXMemory + RGBXIndex) + 0,1);
    

    die Werte

    sizeof(i)==sizeof(RGBXIndex)==sizeof(ColorIndex)
    

    size_t ist doch wie int eine architekturabhängige Größe oder nicht?
    so dass man im Prinzip:

    memcpy(redmemory  + i,((char*)RGBXMemory + i) + 2,1);
    memcpy(bluememory + i,((char*)RGBXMemory + i) + 1,1);
    memcpy(greenmemory+ i,((char*)RGBXMemory + i) + 0,1);
    

    schreiben kann?
    Da char ja immer 1 sein muss kann man sich die zweite Klammer auch sparen.

    memcpy(redmemory  + i,(char*)RGBXMemory+i+2,1);
    memcpy(bluememory + i,(char*)RGBXMemory+i+1,1);
    memcpy(greenmemory+ i,(char*)RGBXMemory+i,1);
    

    So dass man im Endeffekt das gleich erreicht wenn man folgendes hat:

    for( int i=0; i<number_of_pixels; i++){
    	memcpy(redmemory  + i,(char*)RGBXMemory+i+2,1);
    	memcpy(bluememory + i,(char*)RGBXMemory+i+1,1);
    	memcpy(greenmemory+ i,(char*)RGBXMemory+i+0,1);
    }
    // xxxmemory++==xxxmemory+i
    for( int i=0; i<number_of_pixels; i++){
    	memcpy(redmemory++   ,(char*)RGBXMemory++ +2,1);
    	memcpy(bluememory++  ,(char*)RGBXMemory++ +1,1);
    	memcpy(greenmemory++ ,(char*)RGBXMemory++ +0,1);
    // Dieses hier müsste eigentlich langsamer sein wegen den ++
    }
    

    oder nicht?
    Ohne das Ausgabebild ist es ein wenig schwer zu beurteilen.



  • Ja, ich denke auch, dass das mit boost::thread o.Ä. einfacher zu realisieren ist. Allerdings, bevor man damit loslegt, sollte man prüfen, ob das der gesamten Bildverarbeitung zuträglich ist.



  • ogni42 schrieb:

    Ja, ich denke auch, dass das mit boost::thread o.Ä. einfacher zu realisieren ist. Allerdings, bevor man damit loslegt, sollte man prüfen, ob das der gesamten Bildverarbeitung zuträglich ist.

    Machst du das nicht nebenbei? 🙂



  • EDIT: Ich war dumm und habe die falsche Methode aufgerufen. Hier die korrigierten Zahlen:

    So jetzt mit einer "vernünftig" mit OpenMP parallelisierten Version - per omp_set_num_threads(maxThreads); ist die Gesamtzahl an Threads auf 8 gesetzt:

    `

    Copying with Add based address calculation: Time elapsed 3.219s

    Copying with memcpy based address calculation: Time elapsed 1.92s

    Copying with memcpy_parallel based address calculation: Time elapsed 4.107s

    `

    Unterm Stricht bringt's auf meinem Rechner nichts. Hier noch der Code für die parallele Version. Die beiden anderen Funktionen sind sequentiell.

    void checkPerMemCpyParallel()
    {
        char* redmemory  = getStartOfRedMemory();
        char* bluememory = getStartOfBlueMemory();
        char* greenmemory = getStartOfGreenMemory();  
    
        RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    
        int  number_of_pixels = m_nSizeX*m_nSizeY;
    
    #pragma omp parallel
        {
            size_t ColorIndex=0;
            size_t RGBXIndex=0;
            int offset = m_nSizeY/maxThreads*omp_get_thread_num();
            for( int i=0; i<number_of_pixels/maxThreads; i++)
            {
                memcpy(redmemory  + ColorIndex + offset,((char*)RGBXMemory + RGBXIndex + offset) + 2,1);
                memcpy(bluememory + ColorIndex + offset,((char*)RGBXMemory + RGBXIndex + offset) + 1,1);
                memcpy(greenmemory+ ColorIndex + offset,((char*)RGBXMemory + RGBXIndex + offset) + 0,1);
    
                RGBXIndex++;
                ColorIndex++;
            }
        }
    }
    


  • ogni42 schrieb:

    So jetzt mit einer "vernünftig" mit OpenMP parallelisierten Version - per omp_set_num_threads(maxThreads); ist die Gesamtzahl an Threads auf 8 gesetzt:

    Du hast doch gesagt das du nur zwei Cores hast.

    Hast du es mit zwei Threads probiert? Es nutzt nämlich nichts wenn du mehr Threads rechnen lässt als du Kerne zur Verfügung hast.



  • Hier die Ergebnisse mit 2 Threads:
    `

    Copying with Add based address calculation: Time elapsed 3.156s

    Copying with memcpy based address calculation: Time elapsed 1.937s

    Copying with memcpy_parallel based address calculation: Time elapsed 4.907s

    `

    Also auch nicht besser.

    Ich schätze, dass es an Problemen beim Cache-Zugriff liegt. Ein Thread will auf eine Cache-Line schreiben auf die auch ein anderer geschrieben hat. Dann muss erst alle in den nächste Cache oder Hauptspeicher ent- und wieder geladen werden.

    Ich probiere das jetzt noch auf einem anderen Rechner aus....

    EDIT: Getan! Das sind die Zahlen etwas anders aber die Verhältnisse gleich.



  • Doppelpost..



  • Man muss hier anmerken dass:
    Bisher jeder Thread auf identische Speicherbereiche zugreifen muss.
    Dieser ist hat auch noch weder die optimale Größe noch ein super Alingment.

    Besserer Win32 Thread Aufbau:
    -128bit Alignment (SSE2)
    -Drei Funktionen
    -Drei Threads

    #include <ctime>
    #include <cstdlib>
    #include <iostream>
    #include <windows.h>
    
    #define NUM_THREADS 3
    CRITICAL_SECTION hUpdateMutex;
    HANDLE thread_handles[NUM_THREADS];
    
    const int m_size_x = 2048;
    const int m_nSizeX = 2048;
    const int m_nSizeY = 2048;
    const int number_of_pixels = m_size_x*m_nSizeY;
    
    const int chunkSz = 5*m_nSizeX*m_nSizeY;
    int largeChunk[chunkSz];
    
    char red[chunkSz],green[chunkSz],blue[chunkSz];
    
    struct RGBPixel24{unsigned char r,g,b;};
    struct RGBPixel32{unsigned char r,g,b,x,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13;};
    
    char* getStartOfRedMemory(){return red;}
    char* getStartOfBlueMemory(){return blue;}
    char* getStartOfGreenMemory(){return green;}
    void* getImageStart(void){return largeChunk;}
    RGBPixel32* getStartOfRGBXMemory(){return reinterpret_cast<RGBPixel32*>(getImageStart());}
    
    void checkPerfMemCpyR(){
    	RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    	char* redmemory  = getStartOfRedMemory();
    	for(int i=0;i<number_of_pixels;i++) memcpy(redmemory+i,(char*)RGBXMemory+i+2,1);
    } 
    
    void checkPerfMemCpyG(){
    	RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    	char* greenmemory = getStartOfGreenMemory();  
    	for(int i=0;i<number_of_pixels;i++) memcpy(greenmemory+i,(char*)RGBXMemory+i,1);
    } 
    
    void checkPerfMemCpyB(){
    	RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    	char* bluememory = getStartOfBlueMemory();
    	for(int i=0;i<number_of_pixels;i++) memcpy(bluememory+i,(char*)RGBXMemory+i+1,1);
    } 
    
    void checkPerfMemCpy(){
    
    	char* redmemory  = getStartOfRedMemory();
    	char* bluememory = getStartOfBlueMemory();
    	char* greenmemory = getStartOfGreenMemory();  
    	RGBPixel32* RGBXMemory = getStartOfRGBXMemory();
    
    	for(int i=0;i<number_of_pixels;i++){
    		memcpy(redmemory+i,(char*)RGBXMemory+i+2,1);
    		memcpy(bluememory+i,(char*)RGBXMemory+i+1,1);
    		memcpy(greenmemory+i,(char*)RGBXMemory+i,1);
    	}
    } 
    
    int main( void ){
    
    	DWORD threadID;
    	clock_t start=0,stop=0;
    	for(int j=0;j<5;j++){
    		std::cout << "Benchmark Nr. " << j+1 << '\n';
    		start=clock();
    		for (int i=0;i<1000;i++) {
    			InitializeCriticalSection(&hUpdateMutex);
    			thread_handles[0] = CreateThread(0,0,(LPTHREAD_START_ROUTINE) checkPerfMemCpyR,0,0,&threadID);
    			thread_handles[1] = CreateThread(0,0,(LPTHREAD_START_ROUTINE) checkPerfMemCpyG,0,0,&threadID);
    			thread_handles[2] = CreateThread(0,0,(LPTHREAD_START_ROUTINE) checkPerfMemCpyB,0,0,&threadID);
    			WaitForMultipleObjects(NUM_THREADS,thread_handles,TRUE,INFINITE);
    		}
    		stop=clock();
    
    		std::cout << "Copying with Win32-Thread memcpy based address calculation: ";
    		std::cout << 1000*(stop-start)/CLOCKS_PER_SEC << '\n';
    
    		start=clock();
    		for (int i=0;i<1000;i++) checkPerfMemCpy();
    		stop=clock();
    
    		std::cout << "Copying with memcpy based address calculation: ";
    		std::cout << 1000*(stop-start)/CLOCKS_PER_SEC << "\n\n";
    	}
    }
    

    Unabhängig von den Optimierungen müsste die Struktur eines Win32 Programms wie oben angegeben aussehen.

    Da im ersten Post die Rede von 5MP war, sind die Werte m_nSizeX,m_nSizeY verdoppelt worden so dass man auf ~4MP kommt.

    Benchmarks:

    Benchmark Nr. 1
    Copying with Win32-Thread memcpy based address calculation: 1558
    Copying with memcpy based address calculation: 2582
    
    Benchmark Nr. 2
    Copying with Win32-Thread memcpy based address calculation: 1501
    Copying with memcpy based address calculation: 2568
    
    Benchmark Nr. 3
    Copying with Win32-Thread memcpy based address calculation: 1487
    Copying with memcpy based address calculation: 2577
    
    Benchmark Nr. 4
    Copying with Win32-Thread memcpy based address calculation: 1459
    Copying with memcpy based address calculation: 2569
    
    Benchmark Nr. 5
    Copying with Win32-Thread memcpy based address calculation: 1461
    Copying with memcpy based address calculation: 2569
    

Anmelden zum Antworten