C/C++ beste Möglichkeit, eine Anzahl von Bytes an stdout zu senden
-
22-08-2019 - |
Frage
Die Profilerstellung meines Programms und der Funktion print nimmt viel Zeit in Anspruch.Wie kann ich die „rohe“ Byteausgabe direkt an stdout senden, anstatt fwrite zu verwenden, und sie schneller machen (müssen alle 9 Bytes in print() gleichzeitig an stdout senden)?
void print(){
unsigned char temp[9];
temp[0] = matrix[0][0];
temp[1] = matrix[0][1];
temp[2] = matrix[0][2];
temp[3] = matrix[1][0];
temp[4] = matrix[1][1];
temp[5] = matrix[1][2];
temp[6] = matrix[2][0];
temp[7] = matrix[2][1];
temp[8] = matrix[2][2];
fwrite(temp,1,9,stdout);
}
Matrix ist global als vorzeichenlose Zeichenmatrix definiert[3][3];
Lösung
IO ist nicht ein kostengünstiger Betrieb. Es ist in der Tat ein Blockierung Betrieb, was bedeutet, dass das Betriebssystem Ihres Prozesses vorgreifen können, wenn Sie write
rufen mehr CPU-gebundene Prozesse laufen zu lassen, bevor das IO-Device sind Sie das schriftlich abgeschlossen Betrieb.
Die einzige untere Ebene Funktion, die Sie (wenn Sie die Entwicklung auf einer * nix-Maschine) verwenden können, ist die rohe write
Funktion zu nutzen, aber selbst dann wird Ihre Leistung nicht so viel schneller, als es jetzt ist. Einfach ausgedrückt: IO ist teuer.
Andere Tipps
Die am besten bewertete Antwort behauptet, dass IO langsam ist.
Hier ist eine schnelle Benchmark mit einem ausreichend großen Puffer, um die OS aus dem kritischen Leistungs Weg zu nehmen, aber nur, wenn Sie bereit sind, Ihre Ausgabe in riesigen blurps zu erhalten. Wenn Latenz zum ersten Byte Ihr Problem ist, müssen Sie in „tröpfchen“ Modus auszuführen.
schreiben 10 Millionen Datensätze aus einem neun Byte-Array
Mint 12 AMD64 auf 3GHz CoreDuo unter gcc 4.6.1
340ms to /dev/null
710ms to 90MB output file
15254ms to 90MB output file in "dribs" mode
FreeBSD 9 AMD64 auf 2,4 GHz CoreDuo unter Klirren 3.0
450ms to /dev/null
550ms to 90MB output file on ZFS triple mirror
1150ms to 90MB output file on FFS system drive
22154ms to 90MB output file in "dribs" mode
Es gibt nichts, langsam über IO, wenn Sie sich leisten können, richtig puffern.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[])
{
int dribs = argc > 1 && 0==strcmp (argv[1], "dribs");
int err;
int i;
enum { BigBuf = 4*1024*1024 };
char* outbuf = malloc (BigBuf);
assert (outbuf != NULL);
err = setvbuf (stdout, outbuf, _IOFBF, BigBuf); // full line buffering
assert (err == 0);
enum { ArraySize = 9 };
char temp[ArraySize];
enum { Count = 10*1000*1000 };
for (i = 0; i < Count; ++i) {
fwrite (temp, 1, ArraySize, stdout);
if (dribs) fflush (stdout);
}
fflush (stdout); // seems to be needed after setting own buffer
fclose (stdout);
if (outbuf) { free (outbuf); outbuf = NULL; }
}
Die rawest Form von Ausgang ist Sie tun können, die wahrscheinlich der write
Systemaufruf, wie diese
write (1, matrix, 9);
1 die Dateideskriptor für Standard-out (0 ist Standard in und 2 Standardfehler). Ihr Standard-out wird nur schreiben so schnell wie den man es am anderen Ende (das heißt das Endgerät oder das Programm, das Sie pipeing in) zu lesen, die eher langsam sein könnten.
Ich bin nicht 100% sicher, aber Sie könnten versuchen, auf fd 1 (mit fcntl
) non-blocking IO Einstellung und hoffen, dass das Betriebssystem es für Sie puffern, bis sie mit dem anderen Ende verbraucht werden kann. Es ist schon eine Weile, aber ich denke, es funktioniert wie folgt
fcntl (1, F_SETFL, O_NONBLOCK);
YMMV though. Bitte korrigieren Sie mich, wenn ich auf die Syntax falsch bin, wie gesagt, es ist eine Weile her.
Vielleicht ist Ihr Problem ist nicht, dass fwrite () ist langsam, aber dass es gepuffert. Versuchen Sie fordern fflush (stdout) nach dem fwrite ().
Das alles hängt wirklich von Ihrer Definition von langsam in diesem Zusammenhang.
Alle Druck ist ziemlich langsam, obwohl iostreams für den Druck wirklich langsam ist.
Ihre beste Wette wäre printf zu verwenden, etwas entlang der Linien von:
printf("%c%c%c%c%c%c%c%c%c\n", matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0],
matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2]);
Sie können einfach:
std::cout << temp;
printf ist C-Style.
Doch IO-Operationen sind teuer, so nutzen sie mit Bedacht aus.
Wie jeder darauf hingewiesen hat, ist IO in einer engen inneren Schleife teuer.Normalerweise habe ich Matrix auf der Grundlage einiger Kriterien bedingt ausgeschlossen, wenn es zum Debuggen erforderlich war.
Wenn es sich bei Ihrer App um eine Konsolen-App handelt, versuchen Sie, sie in eine Datei umzuleiten. Das geht viel schneller als Konsolenaktualisierungen.z.B. app.exe > matrixDump.txt
Was ist los mit:
fwrite(matrix,1,9,stdout);
das eine wie die zweidimensionalen Arrays den gleichen Speicher in Anspruch nehmen.
Versuchen Sie das Programm zweimal ausgeführt wird. Einmal mit und einmal ohne Ausgang. Sie werden feststellen, dass insgesamt das eine ohne das io der schnellste ist. Auch Sie könnten den Prozess Gabel (oder einen Thread erstellen), ein Schreiben in eine Datei (stdout) und eine der Operationen zu tun.