Manera eficiente de guardar datos en el disco mientras se ejecuta una tarea computacionalmente intensiva

StackOverflow https://stackoverflow.com/questions/1014113

Pregunta

Estoy trabajando en una pieza de software científico que requiere mucha CPU (está vinculado a proceso), pero necesita escribir datos en el disco con bastante frecuencia (enlazado de E / S).

Estoy agregando paralelización a esto (OpenMP) y me pregunto cuál es la mejor manera de abordar las necesidades de escritura en disco. No hay razón para que la simulación espere en el HDD (que es lo que está haciendo ahora).

Estoy buscando una 'mejor práctica' para esto, y la velocidad es lo que más me importa (pueden ser simulaciones muy largas).

Gracias ~ Alex

Primeros pensamientos:

tener un proceso separado realiza la escritura real en el disco para que la simulación tenga dos procesos: uno está vinculado a la CPU (simulación) y otro está vinculado a la IO (archivo de escritura). Esto suena complicado.

¿Posiblemente una tubería / buffer? Soy un poco nuevo en esto, así que tal vez podría ser una posible solución.

¿Fue útil?

Solución

Si implementa OpenMP en su programa, entonces es mejor usar #pragma omp single o #pragma omp master de la sección paralela para guardar en el archivo. Estos pragmas permiten que solo un hilo ejecute algo. Por lo tanto, su código puede tener el siguiente aspecto:

#pragma omp parallel
{
    // Calculating the first part
    Calculate();

    // Using barrier to wait all threads
    #pragma omp barrier

    #pragma omp master
    SaveFirstPartOfResults();

    // Calculate the second part
    Calculate2();

    #pragma omp barrier

    #pragma omp master
    SaveSecondPart();

    Calculate3();

    // ... and so on
}

Aquí el equipo de subprocesos hará el cálculo, pero solo un subproceso guardará los resultados en el disco.

Parece una tubería de software. Le sugiero que considere el patrón tbb :: pipeline de la biblioteca Intel Threading Building Blocks. Puedo remitirlo al tutorial sobre las tuberías de software en http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25 . Por favor lea el párrafo 4.2. Resolvieron el problema: un hilo para leer desde la unidad, el segundo para procesar cadenas de lectura, el tercero para guardar en la unidad.

Otros consejos

Diría que la mejor manera sería generar un hilo diferente para guardar los datos, no un proceso completamente nuevo; con un nuevo proceso, tiene la molestia de tener que comunicar los datos que se guardarán a través del límite del proceso, lo que presenta un nuevo conjunto de dificultades.

La primera solución que viene a la mente es más o menos lo que ha dicho: tener escrituras en disco en su propio proceso con una tubería unidireccional desde el sim al escritor. El escritor escribe lo más rápido posible (extrayendo nuevos datos de la tubería). El problema con esto es que si el sim se adelanta demasiado al escritor, el sim se bloqueará en las escrituras de la tubería de todos modos, y estará unida a E / S en una extracción.

El problema es que, de hecho, su ciclo de simulación no está completo hasta que escupe los resultados.

Lo segundo que se me ocurre es usar E / S sin bloqueo. Cada vez que el sim necesita escribir, debe hacerlo a través de E / S sin bloqueo. En la siguiente necesidad de escritura, puede recoger los resultados de la operación de E / S anterior (posiblemente incurriendo en una pequeña espera) antes de comenzar la nueva. Esto mantiene la simulación funcionando tanto como sea posible en paralelo con la E / S sin permitir que la simulación avance mucho antes de la escritura.

La primera solución sería mejor si el ciclo de procesamiento de la simulación varía (a veces más pequeño que el tiempo de una escritura, a veces más largo) porque en promedio las escrituras podrían mantenerse al día con el sim.

Si el ciclo de procesamiento es siempre (o casi siempre) más corto que el tiempo de escritura  entonces es mejor no molestarse con la tubería y simplemente usar E / S sin bloqueo, porque si usa la tubería, eventualmente se llenará y el sim se colgará en la E / S de todos modos.

Ya que estás vinculado a la CPU y al IO: Déjame adivinar: Todavía hay mucha memoria disponible, ¿verdad?

Si es así, debe almacenar en búfer los datos que deben escribirse en el disco en la memoria hasta cierto punto. Escribir grandes cantidades de datos suele ser mucho más rápido que escribir pequeñas piezas.

Para la escritura en sí: considere usar memoria asignada IO. Ha pasado un tiempo desde la evaluación comparativa, pero la última vez que lo hice fue significativamente más rápido.

Además, siempre puedes intercambiar CPU vs. IO un poco. Creo que actualmente está escribiendo los datos como algún tipo de datos sin procesar, sin comprimir, ¿verdad? Puede obtener algo de rendimiento de E / S si utiliza un esquema de compresión simple para reducir la cantidad de datos que se escribirán. La biblioteca ZLIB es bastante fácil de trabajar y se comprime muy rápido en el nivel de compresión más bajo. Depende de la naturaleza de sus datos, pero si hay mucha redundancia, incluso un algoritmo de compresión muy burdo puede eliminar el problema de IO.

Un hilo ejecuta continuamente un paso del proceso computacionalmente intensivo y luego agrega el resultado parcial a una cola de resultados parciales. Otro hilo elimina continuamente resultados parciales de la cola y los escribe en el disco. Asegúrese de sincronizar el acceso a la cola. Una cola es una estructura de datos similar a una lista donde puede agregar elementos al final y eliminar elementos del frente.

Haga que su aplicación tenga dos subprocesos , uno para la CPU y otro para el disco duro.

Haga que el hilo de la CPU empuje los datos completados en una cola que el hilo del disco duro extrae a medida que ingresan los datos.

De esta forma, la CPU simplemente elimina los datos y permite que otra persona los maneje, y el disco duro espera pacientemente cualquier dato en su cola.

En cuanto a la implementación, podría hacer la cola como un tipo de objeto de memoria compartida, pero creo que una tubería sería exactamente lo que estaría buscando. La CPU simplemente escribe en la tubería cuando es necesario. En el lado del disco duro, solo leería la tubería y cada vez que obtenga datos válidos, proceda desde allí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top