2010-03-04 8 views
7

Estoy ejecutando código de simulación que está en gran medida vinculado por la velocidad de la CPU. No estoy interesado en ingresar/sacar datos a una interfaz de usuario, simplemente guardarla en el disco a medida que se computa.Todas las cosas son iguales ¿cuál es la forma más rápida de generar datos en disco en C++?

¿Cuál sería la solución más rápida que reduciría la sobrecarga? iostreams? printf? He leído anteriormente que printf es más rápido. ¿Esto dependerá de mi código y es imposible obtener una respuesta sin perfiles?

Esto se ejecutará en Windows y los datos de salida deben estar en formato de texto, separados por comas/tabulaciones, con opciones de formato/precisión para valores de coma flotante en su mayoría.

+2

¿Qué pasa con los perfiles? O en tu caso, simplemente cronometrando? –

+0

Nada, aparte de necesitar un punto de partida. –

+3

Existe una plétora de sutilezas involucradas en la maximización de IO de disco, probablemente sea mejor leer algunos documentos de personas que ya han hecho el perfil. –

Respuesta

3

Mi idea es que estás abordando el problema equivocado. ¿Por qué estás escribiendo grandes cantidades de datos con formato de texto?Si es porque quieres que sea legible por el ser humano, escribiendo un programa de navegador rápido para leer los datos en formato binario sobre la marcha, de esta manera la aplicación de simulación puede escribir rápidamente datos binarios y el navegador puede hacer el arduo trabajo de formatear el datos como y cuando sea necesario. Si es porque está utilizando algún paquete de estadísticas para leer y analizar datos de texto, escriba uno que ingrese datos binarios.

4

No los he usado, pero he escuchado que los archivos mapeados en memoria ofrecen las mejores oportunidades de optimización para el sistema operativo.

Editar: relacionado question, y Wikipedia article on memory mapped files - ambos mencionan los beneficios de rendimiento.

+0

Lástima que no hay una manera potable :(+1 –

4

Construya bloques de datos (grandes) que se pueden escribir secuencialmente y usan IO asíncrona.

Perfilar con precisión será doloroso, lea algunos documentos sobre el tema: scholar.google.com.

0

La forma más rápida es basada en la compleción asincrónica IO.

Al darle al sistema operativo un conjunto de datos para escribir, que no se han escrito cuando la llamada vuelve, el sistema operativo puede reordenarlos para optimizar el rendimiento de escritura.

La API para hacerlo es específica del sistema operativo: en Linux, se llama AIO; en Windows se llama Completion Ports.

1

Abra el archivo en modo binario y escriba datos "sin formatear" en el disco.

fstream myFile; 
... 
myFile.open ("mydata.bin", ios:: in | ios::out | ios::binary); 
... 
class Data { 
    int  key; 
    double value; 
    char[10] desc; 
}; 

Data x; 

myFile.seekp (location1); 
myFile.write ((char*)&x, sizeof (Data)); 

EDIT: El PO añadió los "datos de salida tiene que estar en formato de texto, ya sea pestaña o separados por comas." restricción.

Si su aplicación está vinculada a la CPU, el formateo de la salida es una sobrecarga que no necesita. Los datos binarios son mucho más rápidos de escribir y leer que ascii, es más pequeño en el disco (por ejemplo, hay menos bytes totales escritos con binario que con ascii), y como es más pequeño, es más rápido moverse por una red (incluida una red montada). sistema de archivos). Todos los indicadores apuntan a binario como una buena optimización general.

La visualización de los datos binarios se puede realizar después de la ejecución con una sencilla utilidad que arrojará los datos a ascii en el formato que sea necesario. Me gustaría animar a que se agregue cierta información de versión a los datos binarios resultantes para garantizar que los cambios en el formato de los datos se puedan manejar en la herramienta de volcado.

Cambiar de binario a ascii, y luego objetar el rendimiento relativo de printf frente a iostreams probablemente no sea el mejor uso de su tiempo.

3

El punto más eficaz C++ de Scott Meyers, 23 "Considere bibliotecas alternativas" sugiere usar stdio sobre iostream si prefiere la velocidad sobre la seguridad y la extensibilidad. Vale la pena verificarlo.

2

La manera más rápida es la que es más rápida para su aplicación en particular que se ejecuta en su sistema operativo y hardware típicos. Lo único sensato que se puede hacer es probar varios enfoques y cronometrarlos. Probablemente no necesite un perfil completo, y el ejercicio solo debería tomar unas pocas horas. Me gustaría probar, en este orden:

  • normal de corriente C++ I O
  • corriente/normal de I/O usando ostream :: write()
  • uso de la biblioteca CI/O
  • uso de llamadas al sistema, tales como escritura()
  • asynch E/S

Y me detenía cuando encontré una solución que era lo suficientemente rápido.

2

El formato de texto significa que es para consumo humano. La velocidad a la que los humanos pueden leer es muy, muy inferior a la velocidad de cualquier método de salida razonable. Hay una contradicción en alguna parte. Sospecho que la "salida debe ser formato de texto".

Por lo tanto, creo que la versión correcta es la de salida binaria y proporciona un visor independiente para convertir entradas individuales en texto legible. El formateo en el visor solo debe ser tan rápido como las personas puedan leer.

0

Un método rápido es utilizar doble almacenamiento en búfer y varios hilos (al menos dos).

Un hilo es el encargado de escribir datos en el disco duro. Esta tarea comprueba el búfer y si no está vacío (o quizás otra regla) comienza a escribir en el disco duro.

El otro hilo escribe texto formateado en el búfer.

Un problema de rendimiento con los discos duros es la cantidad de tiempo necesaria para ponerse a la velocidad y ubicar el cabezal en la ubicación correcta. Para evitar que esto suceda, el objetivo es escribir continuamente en el disco duro para que no se detenga. Esto es complicado y puede involucrar cosas fuera del alcance de su programa (como otros programas que se ejecutan al mismo tiempo). Cuanto mayor sea la cantidad de datos escritos en el disco duro, mejor.

Otra espina es encontrar ranuras vacías en el disco duro para poner los datos. Un disco duro fragmentado sería más lento que un disco formateado o desfragmentado.

Si la portabilidad no es un problema, puede verificar su sistema operativo para algunas API que realizan escrituras en bloque en el disco duro. O puede bajar más abajo y usar la API que escribe directamente en la unidad.

Es posible que también desee que su programa cambie su prioridad para que sea una de las tareas más importantes que se ejecutan.

+1

No estoy seguro de que agregar hilos para IO sea el movimiento correcto. El ciclo computacional principal está vinculado a la CPU. Si la máquina es multinúcleo, entonces una mejor optimización general probablemente debe agregar el paralelismo a la parte computacional del código. Si la máquina no es multinúcleo, agregar subprocesos para IO cuando el lazo principal ya está vinculado a la CPU no puede aumentar el rendimiento general de la aplicación. –

1

Asignando el archivo a la memoria (es decir, usando un Memory Mapped File), entonces solo memcopy -datos hay una manera muy rápida de leer/escribir.

Puede utilizar varios hilos/núcleos para escribir en los datos, y el sistema operativo/kernel sincronizará las páginas en el disco, utilizando el mismo tipo de rutinas utilizadas para la memoria virtual, que se puede esperar optimizar al infierno y de vuelta, más o menos.

Principalmente, debe haber algunas copias/búferes adicionales en la memoria al hacer esto. Las escrituras son atrapadas por interrupciones y agregadas a la cola del disco una vez que se ha escrito una página.

+0

Esto no proporciona un responda a la pregunta. Para criticar o solicitar aclaraciones de un autor, deje un comentario debajo de su publicación. –

+1

@Jav_Rock: Reescribió la respuesta, ojalá sea mejor ahora. – Macke

Cuestiones relacionadas