C++11 STL Threads - Speicherproblem (erledigt)



  • Hi zusammen

    ich habe einen Fall, in dem ich zur Parallelisierung von Berechnungen mehrfach
    STL-Threads starte und wieder joine.
    Umgebung:
    Codeblocks 13.12 mit mingw64-Compiler, Windows7 64bit

    Laut Windows-Taskmanager steigt der Speicherkonsum der Anwendung stark an, obwohl das laut Sourcecode eigentlich nicht passieren sollte.

    Ich habe meinen Anwendungsfall mal stark reduziert.
    Das Problem tritt aber noch auf.

    #include <vector>
    #include <thread>
    
    int main( int argc, char **argv )
    {
        for ( unsigned j = 0; j < 10000; ++j )
        {
            std::vector<std::thread> Threads;
    
            // Erzeugen Threads
            for ( unsigned i = 0; i < 40; ++i )
                Threads.push_back( std::thread( []( unsigned i ) { for ( unsigned k = 0; k < 1000000; ++k ) ++i; }, i ) );
    
            // Warten bis Threads fertig sind
            for( auto &th : Threads )
                th.join();
        }
        return 0;
    }
    

    Ist das irgendwie erklärbar? Hoffentlich kein Memory-Leak in der Thread-Implementation... Oder einfach eine Falschaussage des Taskmanagers?



  • Und wo wird da Speicher freigegeben?



  • Ich gehe davon aus, dass die Thread-Objekte sauber sterben, wenn der Vector stirbt.



  • It0101 schrieb:

    Ich gehe davon aus, dass die Thread-Objekte sauber sterben, wenn der Vector stirbt.

    D.h., der Speicherverbrauch steigt mit der Anzahl der Iterationen der äusseren Schleife? Wie viel pro Iteration?



  • Sicher dass du in der Schleife des Lambdas i erhöhen willst und nicht k?
    Mein MSVC2015 sagt nämlich Error dazu (was ja auch logisch ist, der kann ja keine Variablen capturen). Wenn ich den parameter des Lambdas umbenenne und auch eben das Inkrement anpasse gehts.
    Aber von Speicheranstieg keine Spur.

    #include <vector>
    #include <thread>
    
    int main(int argc, char **argv)
    {
    	for (unsigned j = 0; j < 10000; ++j)
    	{
    		std::vector<std::thread> Threads;
    
    		// Erzeugen Threads
    		for (unsigned i = 0; i < 40; ++i)
    			Threads.push_back(
    				std::thread(
    					[](unsigned x) // dieses war vorher i
    		{
    			for (unsigned k = 0; k < 1000000; ++k)
    				++x; // das war auch i
    		}, i));
    
    		// Warten bis Threads fertig sind
    		for (auto &th : Threads)
    			th.join();
    	}
    	return 0;
    }
    


  • Du hast doch jetzt nur mein "i" im Lambda einfach umbenannt. Das ändert doch nichts. Da das Lamba keinen Zugriff auf die äußeren Variablen hat ( "[ ]" ), stört das nicht, dass das "i" quasi auf den ersten Blick doppelt ist.

    Ich habe das jetzt bei mir auf meinem Linux laufen lassen und da war im "top" auch keine Spur von Anstieg. Scheint bei mir wirklich ein Fehler im Taskmanager zu sein, bzw. eine Fehlwahrnehmung. Ich kriege ja auch kein BadAlloc...



  • manni66 schrieb:

    It0101 schrieb:

    Ich gehe davon aus, dass die Thread-Objekte sauber sterben, wenn der Vector stirbt.

    D.h., der Speicherverbrauch steigt mit der Anzahl der Iterationen der äusseren Schleife? Wie viel pro Iteration?

    Es war in dem Fall ein paar MB pro Sekunde... keine Ahnung wie viel pro Iteration.



  • It0101 schrieb:

    Es war in dem Fall ein paar MB pro Sekunde... keine Ahnung wie viel pro Iteration.

    Mit VS 2015 steigt es langsam von 0,7 MB auf 1,5 MB am Ende an. Wenn man zigtausende Threads startet und schließt, bleibt vielleicht auch etwas Müll liegen.



  • It0101 schrieb:

    Laut Windows-Taskmanager steigt der Speicherkonsum der Anwendung stark an, obwohl das laut Sourcecode eigentlich nicht passieren sollte.

    Du vergisst hierbei den Stack. Jeder Thread bekommt seinen eigenen Stack. Die Größe des Stacks kannst Du aber leider nicht über die C++11 Thread API beeinflussen. Das ist system- und implementierungsspezifisch.

    Relevant:
    https://stackoverflow.com/questions/13871763/how-to-set-the-stacksize-with-c11-stdthread



  • Der Stack eines Threads wird aber wieder freigegeben, sobald der Thread stirbt. Und das tun meine Threads hoffentlich. 😉

    Unter Linux steigt der Speicher nicht an. Daher ist das bei mir einfach dem dämlichen TaskManager von Windoof geschuldet.


  • Mod

    Taskmanager sind keine Profilingtools. Taskmanager sind als nette, bunte Übersicht für DAUs gedacht, welche Anwendung ungefähr was macht. Was da tatsächlich angezeigt wird ist ziemlich komplex und für die Analyse von Programmen ungeeignet. Wenn du deine Programme analysieren willst, nutz Werkzeuge, die dafür gedacht sind. Damit bekommst du genauere Informationen, deren Bedeutung klarer definiert ist und die für die Programmierung tatsächlich relevant sind.


Anmelden zum Antworten