Il modo migliore in C/C++ per inviare un numero di byte a stdout
-
22-08-2019 - |
Domanda
La profilazione del mio programma e la funzione print richiedono molto tempo.Come posso inviare l'output di byte "grezzo" direttamente a stdout invece di utilizzare fwrite e renderlo più veloce (è necessario inviare tutti i 9 byte in print() contemporaneamente allo stdout)?
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);
}
La matrice è definita globalmente come una matrice di caratteri senza segno[3] [3];
Soluzione
IO non è un'operazione poco costoso. E ', infatti, un blocco il funzionamento, il che significa che il sistema operativo può prevenire il processo quando si chiama write
per consentire a più processi CPU-bound per l'esecuzione, prima che il dispositivo IO che si sta scrivendo per la completa operazione.
La funzione solo il primo ciclo è possibile utilizzare (se si sta sviluppando su una macchina * nix), è quello di utilizzare la funzione write
crudo, ma anche in questo caso le prestazioni non sarà così molto più veloce di quanto lo sia ora. In poche parole: IO è costoso.
Altri suggerimenti
La risposta nominale superiore sostiene che IO è lento.
Ecco un rapido punto di riferimento con un numero sufficientemente ampio di buffer di prendere il sistema operativo di fuori del percorso prestazioni critiche, ma solo se si è disposti a ricevere la vostra uscita nelle blurps giganti. Se la latenza al primo byte è il tuo problema, è necessario eseguire in modalità "spizzichi".
Scrivi 10 milioni di dischi da un array di byte nove
Mint 12 AMD64 su 3GHz CoreDuo sotto gcc 4.6.1
340ms to /dev/null
710ms to 90MB output file
15254ms to 90MB output file in "dribs" mode
FreeBSD 9 AMD64 su 2.4GHz CoreDuo sotto clang 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
Non c'è niente lenta in merito a IO se si può permettere di buffer in modo corretto.
#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; }
}
La forma più cruda di uscita si può fare è la probabile la chiamata di sistema write
, come questo
write (1, matrix, 9);
1 è il descrittore di file per standard out (0 è standard, e 2 è errore standard). Il vostro fuori standard sarà solo scrivere veloce come quella lettura all'altra estremità (vale a dire il terminale, o il programma che stai pipeing in), che potrebbe essere piuttosto lento.
Non sono sicuro al 100%, ma si potrebbe provare a impostare non-blocking IO su fd 1 (utilizzando fcntl
) e sperare che il sistema operativo sarà tampone per voi fino a che non può essere consumato da l'altra estremità. E 'stato un po', ma penso che funziona in questo modo
fcntl (1, F_SETFL, O_NONBLOCK);
YMMV però. Si prega di correggermi se sbaglio sulla sintassi, come ho detto, è stato un po '.
Forse il tuo problema non è che fwrite () è lento, ma che è tamponato. Prova a chiamare fflush (stdout) dopo il fwrite ().
Questo dipende tutti davvero dalla vostra definizione di lento in questo contesto.
Tutto stampa è piuttosto lento, anche se iostreams sono veramente lento per la stampa.
La cosa migliore sarebbe quella di utilizzare printf, qualcosa sulla falsariga di:
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]);
Si può semplicemente:
std::cout << temp;
printf è più C-Style.
Tuttavia, le operazioni di IO sono costosi, in modo da utilizzare con saggezza.
Come tutti hanno sottolineato, l'IO in un circuito interno ristretto è costoso.Normalmente finisco per eseguire il cout condizionale di Matrix in base ad alcuni criteri quando richiesto per eseguirne il debug.
Se la tua app è un'app console, prova a reindirizzarla a un file, sarà molto più veloce rispetto all'aggiornamento della console.ad esempio app.exe > matriceDump.txt
Cosa c'è di sbagliato con:
fwrite(matrix,1,9,stdout);
l'una e le due matrici dimensionali occupano la stessa memoria.
Provare a eseguire il programma di due volte. Una volta con uscita e una volta senza. Si noterà che, nel complesso, l'uno senza l'io è il più veloce. Inoltre, si potrebbe fork del processo (o creare un filo), una scrittura su un file (stdout), e uno a fare le operazioni.