Frage

Ich habe ein kleines C-Programm Hashes berechnet werden (für Hash-Tabellen). Der Code sieht ziemlich sauber Ich hoffe, aber es ist etwas nicht mit ihm verbundenen, das mich nervt.

Ich kann leicht über eine Million Hashes in etwa 0,2-0,3 Sekunden (gebenchmarkt mit / usr / bin / Zeit) erzeugen. Allerdings, wenn ich printf bin (), um sie in der for-Schleife inging, das Programm verlangsamt sich auf etwa 5 Sekunden.

  1. Warum ist das?
  2. Wie machen es schneller? mmapp () ing stdout vielleicht?
  3. Wie stdlibc in Bezug auf diese ausgelegt ist, und wie sie verbessert werden kann?
  4. Wie könnte die Kernel-Unterstützung es besser? Wie wäre es geändert werden muß, um den Durchsatz auf lokale „Dateien“ (Steckdosen, Leitungen, etc.), um wirklich schnell?

Ich freue mich auf eine interessante und detaillierte Antworten. Danke.

PS: Das ist für einen Compiler Bau Toolset, also nicht von schüchtern in Details zu erhalten. Während das nichts mit dem Problem zu tun hat, selbst, ich wollte nur darauf hinweisen, dass Details mich interessieren.

Nachtrag

Ich suche nach mehr programmatischen Ansätzen für Lösungen und Erklärungen. Tatsächlich Rohrleitungen macht den Job, aber ich habe keine Kontrolle darüber, was die „Nutzer“ der Fall ist.

Natürlich, ich mache einen Test jetzt, die durch „normale Benutzer“ nicht durchgeführt werden würde. Aber das bedeutet nicht die Tatsache ändern, dass ein einfaches printf () verlangsamt ein Verfahren, das ist das Problem, ich versuche, für eine optimale programmatische Lösung zu finden.


Nachtrag - Astonishing Ergebnisse

Die Referenzzeit wird für Normal printf () ruft in einem TTY und dauert etwa 4 Minuten 20 Sekunden.

Testen unter a / dev / pts (z.B. Konsole) beschleunigt die Ausgabe bis etwa 5 Sekunden.

Es dauert ungefähr die gleiche Menge an Zeit, wenn setbuffer () in meinem Test-Code zu einer Größe von 16.384, fast das gleiche für 8192 mit. Ca. 6 Sekunden

setbuffer () hat scheinbar keine Wirkung bei der Verwendung von ihm: es die gleiche Menge an Zeit in Anspruch nimmt (auf einem TTY etwa 4 Minuten, auf einer PTS ca. 5 Sekunden)

.

Die erstaunliche Sache ist, , wenn ich den Test auf TTY1 bin ab und dann Wechsel zu einem anderen TTY , dauert es genau die gleichen wie auf einem PTS: ca. 5 Sekunden.

Fazit : Der Kernel tut etwas, das mit der Zugänglichkeit und Benutzerfreundlichkeit zu tun hat. HUH!

Normalerweise sollte es ebenso langsam egal sein, wenn Sie während seiner aktiven am TTY starren, oder wechseln Sie zu einem anderen TTY.


Lektion : wenn die Ausgangsintensive Programme ausgeführt wird, wechseln Sie zu einem anderen TTY

!
War es hilfreich?

Lösung

Ungepufferte Ausgang ist sehr langsam.

Standardmäßig stdout ist vollständig gepuffert, jedoch, wenn an der Klemme angebracht ist, stdout entweder ungepufferten oder linien gepuffert.

Versuchen Sie, auf Pufferung für stdout wechseln setvbuf() verwenden, wie folgt aus:

char buffer[8192];

setvbuf(stdout, buffer, _IOFBF, sizeof(buffer));

Andere Tipps

Sie könnten speichern Sie Ihre Strings in einem Puffer und geben sie in eine Datei (oder Konsole) am Ende oder in regelmäßigen Abständen, wenn der Puffer voll ist.

Wenn auf einer Konsole ausgibt, Scrollen ist in der Regel ein Killer.

Wenn Sie printf () ing an der Konsole ist es in der Regel extrem langsam. Ich bin mir nicht sicher, warum, aber ich glaube es nicht zurück, bis die Konsole grafisch die ausgegebene Zeichenfolge zeigt. Zusätzlich können Sie nicht () auf stdout mmap.

Schreiben in eine Datei sollte viel schneller (aber immer noch um Größenordnungen langsamer als eine Hash-Berechnung, die alle I / O ist langsam) sein.

Sie können versuchen, Ausgang in der Schale in eine Datei von der Konsole zu umleiten. Mit dieser, Protokolle mit Gigabyte groß kann in nur wenigen Sekunden erstellt werden.

  1. I / O ist immer langsam im Vergleich zu gerade Berechnung. Das System verfügt über Weitere Komponenten zu warten zu sein zur Verfügung, um sie zu nutzen. Es dann muss für die Antwort warten bevor er weitermachen kann. Umgekehrt wenn es einfach ist die Berechnung, dann ist es nur wirklich Daten zwischen den sich bewegenden RAM und CPU-Register.

  2. Ich habe nicht getestet, aber es kann schneller sein, Ihre Hashes auf einen String anhängen, und drucken Sie dann nur die Zeichenfolge am Ende. Obwohl, wenn Sie C verwenden, nicht C ++, kann dies unter Beweis stellen ein Schmerz sein!

3 und 4 sind über mich fürchte ich.

Als I / O immer viel langsamer als CPU Berechnung ist, können Sie alle Werte speichern in schnellstmöglichen I / O zuerst. So RAM verwenden, wenn Sie genug haben, verwenden Sie Dateien, wenn nicht, aber es ist viel langsamer als RAM.

Ausdruck können die Werte nun danach oder parallel von einem anderen Thread ausgeführt werden. So ist die Berechnung Thread (s) müssen nicht warten, bis printf zurückgekehrt ist.

Ich entdeckte schon vor langer Zeit mit diese Technik etwas, das offensichtlich sein sollte. Nicht nur, dass I / O langsam, vor allem an die Konsole, aber die Formatierung Dezimalzahlen nicht schnell entweder. Wenn Sie die Zahlen in binär in großen Puffer setzen können, und schreiben Sie diejenigen in eine Datei, finden Sie es viel schneller ist.

Außerdem, wer geht, sie zu lesen? Es gibt keinen Grund Druck sie alle in einer menschenlesbaren Format, wenn niemand sie alle lesen muss.

  1. Warum nicht die Saiten auf Nachfrage eher, dass an der Stelle der Konstruktion? Es gibt keinen Punkt 40 Bildschirme von Daten in einer Sekunde bei der Ausgabe wie kann man es vielleicht lesen? Warum die Ausgabe nicht erstellen, wie erforderlich und zeigt nur den letzten Bildschirm voll und dann, wie es die Benutzerrollen erforderlich ???

  2. Warum nicht sprintf verwenden, um eine Zeichenfolge zu drucken und dann eine verkettete Zeichenfolge aller Ergebnisse in Speichern und Druck am Ende bauen?

  3. Mit dem man deutlich sprintf Umschalten kann sehen, wie viel Zeit in der Formatumwandlung ausgegeben und wie viel ausgegeben wird das Ergebnis an der Konsole anzeigt und den Code entsprechend ändern.

  4. Konsolenausgang ist definitionsgemäß langsam, wodurch ein Hash nur wenige Bytes an Speicher zu manipulieren. Konsolenausgabe muss durch viele Schichten des Betriebssystems gehen, welcher Code haben zu Thread / Prozess zu behandeln Sperren usw., sobald sie schließlich an den Anzeigetreiber wird das vielleicht ein 9600-Baud-Gerät! oder große Bitmap-Anzeige, einfache Funktionen wie Scrolling des Bildschirms umfassen können Megabyte Speicher zu manipulieren.

Ich denke, der Terminal-Typ ist es, einige der gepufferten Ausgabe verwendet wird, so dass, wenn Sie einen printf es nicht zur Ausgabe in Split Mikrosekunden geschieht, wird in dem Pufferspeicher des Endgeräts Subsystem gespeichert.

Dies könnte durch andere Dinge beeinflusst werden, die eine Verlangsamung verursachen könnte, vielleicht gibt es eine speicherintensive Operation auf sie andere als Ihr Programm ausgeführt wird. Kurz gesagt: es viel zu viele Dinge, die alle zur gleichen Zeit geschehen könnten, Paging, Swapping, schwere i / o von einem anderen Prozess, die Konfiguration des Speichers verwendet, möglicherweise Speicher-Upgrade, und so weiter.

Es wäre besser, die Saiten verketten, bis eine bestimmte Grenze erreicht ist, dann, wenn es, schreiben Sie es auf einmal alle aus. Oder sogar pThreads mit der gewünschten Prozessausführung auszuführen.

Editiert: Wie für 2,3 ist es mir schleierhaft. Für 4, Ich bin nicht vertraut mit Sonne, aber weiß von und werde mit Solaris messed, Es kann eine Kernel-Option sein, einen virtuellen tty zu verwenden .. ich eine Weile, es ist schon zugeben würde, da Messing mit den Kernel-Konfigurationen und neu zu kompilieren es. Als solche Erinnerung an diese möglicherweise nicht groß sein, eine Wurzel mit den Optionen haben, um zu sehen.

user@host:/usr/src/linux $ make; make menuconfig **OR kconfig if from X**

Damit wird das Kernel-Menü anwerfen, haben eine dig um in die Videoeinstellungen Abschnitt unter den Geräten Unterbaum zu sehen ..

Editiert: aber es gibt ein zwicken Sie durch das Hinzufügen einer Datei in das proc-Dateisystem in den Kernel setzen (wenn es so etwas gibt es), oder möglicherweise einen Schalter in den Kernel übergeben, so etwas wie diese (diese einfallsreich ist und es nicht implizieren tatsächlich existiert), FastIO

Hope, das hilft, Freundliche Grüße, Tom.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top