hallo, ich habe ein programm - welches eine 15 MB große Datei (mit float-werten) abspeichert. Dabei steigt kuzrfisitig die CPU-Last auf 100 % - was dazu führt - das andere Prozesse (auch mit höherer Prio) kurzzeitig nicht abgearbeitet werden können. Für das Speichern benutze ich die fprintf(). Dateiformat ist CSV (binär-format senkt die Leistung zwar ein wenig - es kommt trotzdem teilweise zu hängern in den Prozessen). Programmiersprache ist C. Gibt es eine Möglichkeit/Verfahren die CPU beim Speichern einer Datei nicht so stark zu belasten ? ?
Wenn es bei Binary auch noch der Fall ist, dann stimmt etwas mit deinen system nicht. Oder dein Code ist suboptimal. 15mb kann man bequem unter 1s rausschreiben und das ohne CPU last.
Du könntest, anstatt alles in einem Rutsch zu speichern, Dir mehr Zeit dabei lassen, also zwischen n Datensätzen eine Pause einlegen. Oder --sofern es das von Dir nicht erwähnte Betriebssystem zulässt-- die Priorität Deines Prozesses dynamisch reduzieren.
max .. schrieb: > Gibt es eine Möglichkeit/Verfahren die CPU beim Speichern einer Datei > nicht so stark zu belasten ? ? Im Disk-Driver DMA einschalten.
Kann das vielleicht ein Virenscanner sein, der die Datei nochmals analysiert?
Hallo, evtl hilft es die Daten vorher in eine Variable zu schreiben und erst zum Schluss alles auf einmal auf die Platte. Das hat den Vorteil, dass du DMA besser aus nützt da alle Daten auf einmal transportiert werden können anstatt in kleinen Happen. Grüße, Florian
Das sind doch wohl eher die 2 Millionen fprintf die Float in String konvertieren müssen. Wenn es IO wäre würde die CPU Auslastung nicht auf 100% steigen. Siehe z.b. CPU Auslastung in Windows beim Booten.
Udo Schmitt schrieb: > Das sind doch wohl eher die 2 Millionen fprintf die Float in String > konvertieren müssen. er schreibt aber das es auch bei binary der FAll ist. Dazu nimmt man aber nicht fprintf;
Peter II schrieb: > er schreibt aber das es auch bei binary der FAll ist. Dazu nimmt man > aber nicht fprintf; Wenn er damit nur das Format beim Öffnen der Datei meint (fopen("...", "wb")) schon.
hallo, das sind ja schonmal viel anhaltspunkte. danke dafür! also - das mit einem sleep(x) während dem speichern habe schon versucht - alle n-Werte einen sleep von x ms. Da sieht man deutlich wie die CPU Last runtergeht und es kommt auch jeder Prozess wiede dran! ! ! Virenscanner ist durchaus möglich! Aber die Umwandlung von float in string könnte nat. auch die ursache sein! Ich mache mich mal bzgl. dieser 2 Themen schlau - bzw. gehe der Sache mal auf den Grund. An Florian Pfanner: Bzgl. DMA - da kenne ich mich leider nicht aus - kannst du mir da noch etwas konkreter drauf eingehen ?! ?! Danke
max .. schrieb: > Bzgl. DMA - da kenne ich mich leider nicht aus - kannst du mir da noch > etwas konkreter drauf eingehen ?! ?! kopiere einfach mal eine grosse Datei auf deiner Festplatte - wie verhält sich das deine CPU? Sie sollte dabei auf keinen Fall auf 100% gehen. Als nächste teste mal ohne das Rausschreiben, wie sich dann dein Programm verhält.
Hallo, normal musst du dich um DMA nicht kümmern. Das macht das Betriebssystem für dich. Wenn du z.B. eine Datei aus dem RAM auf die Festplatte speichern möchtest, dann gibt das Betriebssystem dem DMA-Controller die Anweisung die Daten vom RAM in den Speicher der Festplatte zu schaufeln. Die CPU muss sich dann nicht weiter darum kümmern und kann seine Zeit mit anderen Threads verbringen. Wenn du aber jetzt ständig kleine Datenmengen schreibst, so hat DMA keinen Einfluss: Das initialisieren der DMA übertragung ist für die CPU dann genau so aufwändig wie das direkte schreiben der Daten an die Festplatte. Man merkt den Unterschied z.B. bei folgenden Schleifen:
1 | for (i=0;i<1000000;i++) |
2 | {
|
3 | fwrite("t", 1, 1, fptr); |
4 | }
|
1 | char buffer[1000000]; |
2 | for (i=0;i<1000000;i++) |
3 | {
|
4 | buffer[i]='t'; |
5 | }
|
6 | fwrite(buffer, 1, 1000000, fptr); |
Im zweiten Fall werden alle Zeichen auf einmal zur Festplatte übertragen, im ersten Fall häppchenweise. Normal ist im Betriebssystem zwar noch ein Puffer dazwischen, aber das zweite Programm ist trotzdem schneller. Deshalb programmiere ich solche ausgeben normalerweise so, dass der Inhalt der Datei erst im RAM zusammengestellt wird und erst im Anschluss in einem Rutsch auf die Platte geschrieben wird. Ich hoffe ich konnte dir damit weiterhelfen, Grüße, Florian
Florian Pfanner schrieb: > Deshalb programmiere ich solche ausgeben normalerweise so, dass der > Inhalt der Datei erst im RAM zusammengestellt wird und erst im Anschluss > in einem Rutsch auf die Platte geschrieben wird. Und dann noch vorbei an irgendwelchen Bibliotheksfunktionen von C (fwrite) sondern direkt mit den OS Funktionen (write unter Unix, WriteFile für die DOSe) Das kann auch nochmal deutlich was bringen. Matthias
Μαtthias W. schrieb: > Und dann noch vorbei an irgendwelchen Bibliotheksfunktionen von C > (fwrite) sondern direkt mit den OS Funktionen (write unter Unix, > WriteFile für die DOSe) Das kann auch nochmal deutlich was bringen. ja uns zwar viele Probleme. Dann dann weiss die C-Lib teilweise nichts von der Datei. Wenn man dann die Datei gleich noch kopiere oder lesen will gibt es merkwürdige effekte. Es mag vieleicht noch mal 0.1% bringen aber ich würde es nicht freiwillig machen.
hi, danke - das sind alles wertvolle tipps. ich habe mal die Konvert - Funktionen von diesem link Beitrag "C-Umwandlungsfunktionen für double/int/long nach String" in mein Programm eingebaut ( da wird in einem Zwischenschritt "manuell" ein Float in einen String gewandelt). Die Vorkonvertierung hat deutlich was an meinen Speicherzeiten bzw. CPU-Auslastung und dem Einhalten des Timings anderer Prozesse gebracht. Speicherzeit von ca. 1.5 s auf 0.3 s gesenkt (leider gibt es selten noch Ausreisser mit 1.5s) -> d.h. der Ansatz scheint richtig zu sein ! ! for( idx = 0; idx < Array->Anzahl; idx++ ) { ftoa( tempbuf, Array->Wert[idx], preC, postC, accuracy ); fprintf( CSVDatei, "%s;\n", tempbuf ); } (wobei Anzahl = 500000 und Wert vom Typ float ist) das einmalige schreiben der Datei hat leider keine Auswirkung im Vergleich zum häppchenweisen schreiben (siehe oben)- da prüfe ich nochmals ob ich da alles richtig mache. Danke soweit.
max .. schrieb: > fprintf( CSVDatei, "%s;\n", tempbuf ); Und da hast du den nächsten printf drin. Da wird wieder Array-Anzahl mal ein printf aufgerufen der Format String geparst etc. Max, es gibt fputs() das ist 10 mal schneller! also { fputs(fp, tempbuf); fputs(fp, "\n"); }
Peter II schrieb: > Μαtthias W. schrieb: >> Und dann noch vorbei an irgendwelchen Bibliotheksfunktionen von C >> (fwrite) sondern direkt mit den OS Funktionen (write unter Unix, >> WriteFile für die DOSe) Das kann auch nochmal deutlich was bringen. > ja uns zwar viele Probleme. Dann dann weiss die C-Lib teilweise nichts > von der Datei. Wenn man dann die Datei gleich noch kopiere oder lesen > will gibt es merkwürdige effekte. > > Es mag vieleicht noch mal 0.1% bringen aber ich würde es nicht > freiwillig machen. Microsoft empfiehlt AUSDRÜCKLICH nicht mehr die file IO Funktionen der C Runtime zu benutzen, sondern die WIN32 API Funktionen. Wir hatten hier mal ein Problem mit einem zyklischen Versatz bei Dateien > 2GByte. Es hatte sich herausgestellt, daß das durch das Schreiben mit stdio Funktionen kam. Ein Request bei Microsoft aufgemacht brachte nur die lapidare Meldung das wäre bekannt und würde auch nicht gefixt, man solle auf die Windows File Funktionen ausweichen. Toll wenn der Code für 3 verschiedene Unixe, Windows, OS/2 und Host laufen musste.
Udo Schmitt schrieb: > Microsoft empfiehlt AUSDRÜCKLICH nicht mehr die file IO Funktionen der C > Runtime zu benutzen, sondern die WIN32 API Funktionen. wenn man nur noch die API Funktionen nutzt ist es ja ok, man sollte nur nicht mixen. Das hatte bei uns mal zu merkwürdigen effekten geführt.
meiner meinung nach sollte man sich zwei buffer machen nicht zu groß, nicht zu klein (sagen wir mal zwischen 4kByte und 1Mbyte ) dazu 2 thread (priority unter normal) der 1 thread bereitet immer die daten auf (zuerst im buffer 1 dann im 2. ) während der 2. thread den buffer 2 auf die platte schreibt (und dann den 1. usw) der schnellere thread muss immer so lange warten bis der nächste buffer fertig ist .. irgendwer schaut noch, dass der langsamere nach jedem lauf eine kurze pause macht.. oder so... der Haupt-thread macht möglichst wenig (messages abarbeiten, progressbar, threads managen...
Robert L. schrieb: > meiner meinung nach sollte man sich zwei buffer machen nicht zu groß, > nicht zu klein (sagen wir mal zwischen 4kByte und 1Mbyte ) > > dazu 2 thread (priority unter normal) > der 1 thread bereitet immer die daten auf (zuerst im buffer 1 dann im 2. > ) Sorry aber man kann auch ein einfaches Speichern von ein paar mehr Daten mit einem Jumbo Jet erschlagen (Meine Meinung) Vieleicht sollte man vorher einfach mal analysieren wo die Zeit verschwendet wird. Hier war es wohl ganz einfach die unbedarfte Benutzung von fprintf(...) in einer Schleife die über ein Millionen Mal durchlaufen wird. Das printf Funktionen teuer sind habe ich in der ersten Woche C lernen gelernt. Ich meine das stand sogar im Kerningham Ritchie.
Udo Schmitt schrieb: > Ein Request bei Microsoft aufgemacht brachte nur die lapidare Meldung > das wäre bekannt und würde auch nicht gefixt, man solle auf die Windows > File Funktionen ausweichen. Na siehst du, wenn dem tatsächlich so ist, wäre das ein guter Grund mehr, endlich weg vom MS-Compiler zu gehen... Ich weiß ja nicht, was und wie dein Programm funktioniert, aber generell empfehle ich ganz dringend: Schreib Programme so, wie sie arbeiten sollen. Wenn ein Programm einen sequenziellen Datenstrom in einer Datei ablegen muss, dann soll das auch schlicht und ergreifend genau so geschehen. Ohne Threads, low-level-I/O, separate Puffer und Zwischenspeicher. Was diese beiden Testprogramme angeht:
1 | /* Variante 1 */
|
2 | for (i=0;i<1000000;i++) |
3 | {
|
4 | fwrite("t", 1, 1, fptr); |
5 | }
|
6 | |
7 | /* Variante 2 */
|
8 | char buffer[1000000]; |
9 | for (i=0;i<1000000;i++) |
10 | {
|
11 | buffer[i]='t'; |
12 | }
|
13 | fwrite(buffer, 1, 1000000, fptr); |
Ich kann exakt garkeinen Unterschied feststellen, selbst auf meiner alten Mühle. Vorallem sollte das aber dein OS nicht ausbremsen. Da solltest du mal nachhaken.
Sven P. schrieb: > Was diese beiden Testprogramme angeht:/* Variante 1 */ > for (i=0;i<1000000;i++) > { > fwrite("t", 1, 1, fptr); > } > > /* Variante 2 */ > char buffer[1000000]; > for (i=0;i<1000000;i++) > { > buffer[i]='t'; > } > fwrite(buffer, 1, 1000000, fptr); > > Ich kann exakt garkeinen Unterschied feststellen, selbst auf meiner > alten Mühle. Vorallem sollte das aber dein OS nicht ausbremsen. Da > solltest du mal nachhaken. Dann hast du falsch getestet. Ich konnte es ohne Problme bei der 10fachen Datenmenge nachvollziehen. Was auch klar ist, dann es sind dann 10.000.000 funktionsaufrufe mehr. Jeder aufruf braucht nun mal ein paar Takte, damit muss es einen unterschied geben. Bei mir waren es bei der 10fache menge 0.1s statt 2 sekunden. > Ich weiß ja nicht, was und wie dein Programm funktioniert, aber generell > empfehle ich ganz dringend: > Schreib Programme so, wie sie arbeiten sollen. Wenn man so rangeht ist ja klar das die PCs immer schneller werden aber die Programme immer langsamer. Man sollte als Programmiere auch mal über den Resourcenverbrauch nachdenken.
Wenn man schon optimieren will dann bitte gleich mit MemoryMappedFiles arbeiten, da buffert das BS gleich selbst ;) Ansonsten stimme ich haku zu, solche Optimierungen ins blaue Bringen selten etwas.. Peter II schrieb: > Man sollte als Programmiere auch mal über > den Resourcenverbrauch nachdenken. Welchen? Dein Programm braucht viel mehr Speicher im zweiten fall ;-P
Peter II schrieb: > Dann hast du falsch getestet. Dann hat er/sie ein falsches Beispielprogramm veröffentlicht. >> Ich weiß ja nicht, was und wie dein Programm funktioniert, aber generell >> empfehle ich ganz dringend: >> Schreib Programme so, wie sie arbeiten sollen. > Wenn man so rangeht ist ja klar das die PCs immer schneller werden aber > die Programme immer langsamer. Das ist Humbug. Es ist nicht deine Aufgabe als Anwendungsprogrammierer, Festplatten-I/O zu optimieren, dafür sind Kernelleute zuständig. Möglicherweise verschlechterst du mit deinen handgemachten Puffern die Performance sogar noch drastisch. Selbstverständlich aber könnte man fprintf() durch fputs() ersetzen, wo es möglich ist. > Man sollte als Programmiere auch mal über > den Resourcenverbrauch nachdenken. Also lieber gleich 64 Bit benutzen, weil sonst der unter Windoof adressierbare Arbeitsspeicher sonst nicht mehr für den Zwischenspeicher ausreicht oder was? PCs werden in erster Linie immer 'langsamer', weil jeder meint, noch zehn Lagen JIT und Script und Wrapper einbauen zu müssen. Mir rollts die Zehennägel auf, wenn ich mir angucke, was sich MS unter effizienter Anwendungsentwicklung vorstellt. Die wichtigste Regel beim Optimieren lautet: Tu es nicht. Die zweit-wichtigste lautet: Tu es noch nicht... Krieg mal nen klaren Kopf und les The Art Of UNIX Programming, das ist wirklich einen Blick wert!
Sven P. schrieb: > Das ist Humbug. Es ist nicht deine Aufgabe als Anwendungsprogrammierer, > Festplatten-I/O zu optimieren, dafür sind Kernelleute zuständig. Es geht hierbei überhaupt nicht um das IO und irgendwelche Puffer. Der unterschied kommt nur von den anzahl der Funktionsaufrufe. Da kann Linux oder MS überhaupt nichts machen - das ist aufgabe das Programmieres. > Mir rollts die > Zehennägel auf, wenn ich mir angucke, was sich MS unter effizienter > Anwendungsentwicklung vorstellt. meinst du .net? Und warum auf MS schimpfen wenn die Firefox leute selber den Browser als HTML darstellen und erweiterungen als Javascript bauen.
Peter II schrieb: > Sven P. schrieb: >> Das ist Humbug. Es ist nicht deine Aufgabe als Anwendungsprogrammierer, >> Festplatten-I/O zu optimieren, dafür sind Kernelleute zuständig. > > Es geht hierbei überhaupt nicht um das IO und irgendwelche Puffer. Der > unterschied kommt nur von den anzahl der Funktionsaufrufe. Da kann Linux > oder MS überhaupt nichts machen - das ist aufgabe das Programmieres. Doch, zwei Beiträge weiter oben geht es um Puffer, und weiter davor um Prioritäten und allerlei Krams. >> Mir rollts die >> Zehennägel auf, wenn ich mir angucke, was sich MS unter effizienter >> Anwendungsentwicklung vorstellt. > meinst du .net? Ja, auch. > Und warum auf MS schimpfen wenn die Firefox leute selber den Browser als > HTML darstellen und erweiterungen als Javascript bauen. Macht es das jetzt besser? FireBug ist ja schon unerträglich langsam. Firefox sowieso.
schön das das thema für so viel gesprächstoff sorgt - aber wir sollten mal bei dem eigentlichen thema bleiben :) wie weiter oben vorgeschlagen - habe ich nun zum einen die konvert-funktion und zum anderen die fputs() verwendet. for( idx = 0; idx < Array->Anzahl; idx++ ) { ftoa( tempbuf, Array->Wert[idx], preC, postC, accuracy ); //fprintf( CSVDatei, "%s;\n", tempbuf ); fputs(tempbuf,CSVDatei); fputs(";\n",CSVDatei); } Ergebnis ist nun - das alle zeiten wieder gesunkten sind - es tauchen jedoch immernoch unregelmäßig zeitliche Peaks auf. Ich denke da spuckt einfach noch etwas anderen mit rein. Aber letztlich wurde durch die ftoa und fputs schon gut optimiert. Damit würde ich dieses Thema abschließen. Danke für die Hilfe - weiter so ! !
Du bist dir dann auch im Klaren, wo ftoa herkommt, ja?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.