C/C++ mejor manera de enviar un número de bytes a stdout
-
22-08-2019 - |
Pregunta
Perfiles de mi programa y la función de impresión está teniendo un montón de tiempo para realizar.¿Cómo puedo enviar un "raw" byte de salida directamente a la salida estándar (stdout) en lugar de utilizar fwrite, y lo que es más rápido (es necesario enviar todos los 9bytes en la impresión (), al mismo tiempo, el 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 matriz se define de forma global a un unsigned char matriz[3][3];
Solución
IO no es una operación de bajo costo. Es, de hecho, un bloqueo operación, lo que significa que el sistema operativo puede anticiparse a su proceso cuando se llama write
para permitir que más procesos vinculados a la CPU para ejecutar, antes de que el dispositivo IO que estás escribiendo a completa el operación.
La función de nivel inferior sólo se puede utilizar (si está desarrollando en una máquina * nix), es utilizar la función write
prima, pero incluso entonces su rendimiento no será mucho más rápido de lo que es ahora. En pocas palabras: IO es caro.
Otros consejos
La respuesta más valorados IO afirma que es lento.
Aquí hay un punto de referencia rápida con un búfer suficientemente grande como para llevar el sistema operativo fuera de la trayectoria de rendimiento crítico, pero sólo si que está dispuesto a recibir su producción en BLURPS gigantes. Si la latencia hasta el primer byte es su problema, que necesita para funcionar en modo "cuentagotas".
Escribir 10 millones de discos a partir de una matriz de nueve bytes
Mint 12 AMD64 en 3GHz CoreDuo bajo gcc 4.6.1
340ms to /dev/null
710ms to 90MB output file
15254ms to 90MB output file in "dribs" mode
FreeBSD 9 AMD64 en 2,4 GHz CoreDuo bajo sonido metálico 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
No hay nada lento en cuanto a IO si puede permitirse el lujo de amortiguar adecuadamente.
#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 más cruda de la producción que puede hacer es lo probable la llamada al sistema write
, como este
write (1, matrix, 9);
1 es el descriptor de fichero para la salida estándar (0 es estándar en, y 2 es el error estándar). Su salida estándar solamente escribirá más rápido que la lectura que en el otro extremo uno (es decir, el terminal o el programa que está en pipeing) que puede ser bastante lento.
No estoy 100% seguro, pero se puede intentar establecer sin bloqueo IO en fd 1 (usando fcntl
) y esperar que el sistema operativo almacenará por usted hasta que pueda ser consumido por el otro extremo. Ha sido un tiempo, pero creo que funciona de la siguiente
fcntl (1, F_SETFL, O_NONBLOCK);
YMMV sin embargo. Por favor, corríjanme si me equivoco en la sintaxis, como ya he dicho, ha sido un tiempo.
Tal vez el problema no es que fwrite () es lento, pero que es amortiguada. Trate de llamar a fflush (stdout) después de la fwrite ().
Todo esto realmente depende de su definición de lento en este contexto.
Toda la impresión es bastante lento, aunque iostreams son muy lento para la impresión.
Su mejor opción sería utilizar printf, algo a lo largo de las líneas de:
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]);
Usted puede simplemente:
std::cout << temp;
printf es más C-Style.
Sin embargo, las operaciones de IO son costosos, por lo que utilizarlos de forma racional.
Como todo el mundo ha señalado IO en apretado lazo interno es caro.He normalmente terminamos haciendo condicional cout de Matriz basada en algunos criterios cuando sea requerido para depurar.
Si su aplicación es la aplicación de consola, a continuación, tratar de redirigir a un archivo, va a ser mucho más rápido que hacer de la consola se actualiza.e.g app.exe > matrixDump.txt
¿Qué hay de malo en:
fwrite(matrix,1,9,stdout);
tanto el uno como las matrices de dos dimensiones ocupan la misma memoria.
Trate de ejecutar el programa dos veces. Una vez con la salida y otra sin él. Se dará cuenta de que, en general, el uno sin el io es el más rápido. También, se puede bifurcar el proceso (o crear un hilo), una escritura en un archivo (stdout), y uno haciendo las operaciones.