Problem mit Dauer der Berechnung



  • Hallo,

    ich habe das Problem, dass mein von mir geschriebener Code zeitlich nicht effektiv zu arbeiten scheint. Darum wollte ich gerne fragen, ob mir von euch jemand einen Tipp geben kann, wie ich das folgende Problem schneller bearbeiten kann.
    Ich habe eine Binärdatei, die ist ca. 4,4 GB groß. In der Datei befinden sich 21,5 Millionen mal (50 Integer-Werte und ein Double-Wert), was das Ergebnis eines Experimentes ist, was ich jetzt gerne auswerten möchte. Diese ganzen Werte aus der Datei zu lesen, dauert nun ungemein lange (ca. 20-30 Minuten). Mein Code dazu ist folgender:

    int				iMax,*iLineDat,iData;
    	bool			bStatus;
    	double		dZahl;
    	fstream		myFile;
    	sRefLine	sData;
    	vector <sRefLine> vsRefLineAll;
    
    	vsRefLineAll.reserve(25000000);
    
    	iMax			= 50;
    	bStatus		= false;
    	iData		= 0;
    	iLineDat	= new int [iMax];
    
     	myFile.open ("D:/data2.bin", ios::in | ios::binary);
    	while (true)
    	{
    		if (myFile.read((char *)iLineDat,iMax*sizeof(iLineDat[0])))
    		{		
    	                sData.fVal0 = 0.312208*Funktion1();
    			if (bStatus)
    			{
    				sData.fVal1 = vsRefLineAll.back().fVal1 + sData.fVal0;
    			}
    			else
    			{
    				iData++;                 
    			}
    		}
    		else
    			break;
    
    		if (myFile.read(reinterpret_cast<char*>(&dZahl), sizeof dZahl))
    		{
    			sData.dTime = dZahl;
    			vsRefLineAll.push_back(sData);
    
    			if (!bStatus)
    			{
    				bStatus = Funktion2();
    			}
    		}
    		else
    			break;
    	}
    
    	delete iLineDat;
    	myFile.close();
    

    In Funktion1 & Funktion2 werden nur einfache Rechenoperationen durchgeführt, die nicht sehr zeitintensiv sind. Darum habe ich sie hier nicht aufgeführt. Des weiteren habe ich versucht, die Daten in einer Liste abzulegen, aber auch das hat eher zu einer Verlangsamung geführt.
    Vielleicht könntet ihr mir einen Hinweis geben?
    Danke.
    V.K.


  • Mod

    Wie sehen den die Signaturen von Funktion1 und Funktion2 aus und wie werden diese tatsächlich aufgerufen (ich nehme an, dass die in Wirklichkeit Parameter haben)? Was tut Funktion2 (abstrakt)?



  • Also,

    so sieht Funktion1 aus:

    float Funktion1 (int iMax,int *iIN);
    float Funktion1 (int iMax,int *iIN)
    {
    	float fM=1.0, fN=0.0;
    	float fThres = 150.0;
    
    	for (int i=14;i<iMax-1;i++)
    	{
    		if (iIN[i+1] >= fThres)
    		{
    			fM = (iIN[i+1] - iIN[i]);
    			fN = iIN[i] - fM * i;
    			return ((fThres-fN)/fM);	
    		}
    	}
    
      return -1;
    }
    

    Funktion2 spielt wirklich keine Rolle, weil sie nach den ersten 20 eingelesenen Werten (d.h. nach 20 while-Durchläufen) nicht mehr aufgerufen wird.

    Vielen Dank!
    V.K.


  • Mod

    Zweifellos kann man diesen Code noch verbessern, allerdings ist zu vermuten, dass der größte Teil der Zeit, mit dem Lesen der Daten zugebracht wird. Wie groß dieser Anteil ist, könntest du abschätzen, indem du die Leseoperation einfach mal auslässt und mit fiktiven Daten arbeitest (dZahl und iLineDat sollten geeignet initailsiert werden, um nicht Rechnungen mit NaNs - die sehr zeitaufwendig sein können - zu riskieren), also ungefähr:

    int count = 21500000;
            while (true)
        {
            if (true)
    ...
    
                break;
    
            if (count--)
            {
                sData.dTime = dZahl;
    

    Die Zeitdifferenz gibt dann Aufschluss darüber, welcher Aspekt am Meisten von einer Optimierung profitieren könnte.



  • wenn man mit ca 50 mb/s die festplatten performance schätzt (was mit heutigen platten eh ein schlechter wert ist), dann sollte das reine lesen ca. 85 sekunden dauern. es muss also wohl etwas anderes der grund sein:
    a) die festplatte gibt weniger als 50 mb/s.
    b) du hast zu wenig ram und das os lagert andauernd daten aus.
    c) deine berechnungen sind doch komplexer als du denkst bzw. du hast etwas übersehen.

    erstes kann durch große fragmentierung möglicherweise passieren. es kann aber auch mit zweiterem zusammenhängen, wenn sich die swap datei/partition auf der gleichen platte wie die datei befindet. das auslagern selbst sollte theoretisch nicht so viel zeit kosten, außer du greifst immer wieder (unabsichtlich) auf ausgelagerte teile zu. wieviel ram hast du denn in dem rechner? zu c fällt mir nichts ein. die c++ api wird kaum der flaschenhals sein, da das anfügen eines elements an eine liste O(1) ist. wenn man jetzt mal irgend einen wert nimmt pro anhängen, der wohl eh falsch ist, könnte das gesamte anfügen wohl zw. 20 (1 μs pro anhängen) und 2 sekunden (100 ns) dauern. campers vorschlag ist schon sehr gut, man könnte ihn mit profiling kombinieren. ich hoffe, ich habe hier keinen all zu großen mist geschrieben. 🙂



  • Hi,

    ich habe den von Camper vorgeschlagenen Test durchgeführt und es hat tatsächlich nur 9,6 Sek. gedauert. Es muss also am Einlesen der Dateien liegen! Ich habe das Programm (Einlesen und Berechnung) auch auf einem anderen Rechner laufen lassen und dort hat es ebenfalls eine halbe Stunde gedauert.

    Wie könnte ich diesen Lesevorgang jetzt beschleunigen?
    Vielen Dank!
    V.K.

    P.S.: Mein Rechner hat 1,4 GB RAM.



  • 1.4 gb ist ein eigenartiger wert, aber ok 🙂
    dann wird wohl das problem sein, dass du die ganzen werte nicht im ram platz hast und das os immer auslagert. vielleicht findest du wen, der dir ram leiht. würde mich auch interessieren, ob es dann schneller geht.



  • natürlich gehts dann schneller,
    macht auch dem computer keinen spass wegen
    jedem datensatz immer in den keller zu gehen,
    weil in der wohnstube kein platz mehr ist



  • besserwisser schrieb:

    dann wird wohl das problem sein, dass du die ganzen werte nicht im ram platz hast und das os immer auslagert. vielleicht findest du wen, der dir ram leiht. würde mich auch interessieren, ob es dann schneller geht.

    Naja, die Werte sollen ja nicht alle auf einmal in den RAM geladen werden (oder doch?). Sonst bekäme man bei 4.4 GB auf 32-Bit-Systemen sowieso Probleme.
    Gerade wenn diese Datei über einen längeren Zeitraum immer wieder vergrößert worden ist (z.B. weil es Messdaten sind), dann wird sie extrem fragmentiert sein. Kannst ja mal die Deframentierung anwerfen und schauen, ob sie zu den Dateien mit den meisten Fragmenten gehört.


Log in to reply