traduccion threading que off juegos desactivar desactivado activar activado multithreading haskell lazy-evaluation ghc thunk

multithreading - que - hyper threading traduccion



¿Cuán atómicos son los giros de GHC? (3)

Desde mainisusuallyafunction.blogspot.com/2011/10/… @Lambdageek vinculada, el comentario de GHC y la guía del usuario de GH, recomiendo lo siguiente:

GHC intenta evitar la reevaluación de los thunks, pero debido a que el bloqueo real entre los hilos es costoso, y los thunk son generalmente puros e inofensivos para reevaluar, normalmente lo hace de manera descuidada, con una pequeña posibilidad de duplicar el trabajo de todos modos.

El método que utiliza para evitar el trabajo es reemplazar los thunk por un blackhole , un marcador especial que le dice a otros hilos (o a veces, el hilo en sí, así es como ocurre la detección <<loop>> ) que el thunk está siendo evaluado.

Dado esto, hay al menos tres opciones:

  • Por defecto, usa "blackholing perezoso", donde esto solo se hace antes de que el hilo esté a punto de pausar. Luego "recorre" su pila y crea "verdaderos" agujeros negros para los nuevos thunk, usando el bloqueo para asegurar que cada thunk solo consiga un thread blackholing, y abortando su propia evaluación si descubre que otro thread ya ha oscurecido un thunk. Esto es más barato, ya que no necesita considerar los thunk cuyo tiempo de evaluación es tan corto que se ajusta completamente entre dos pausas.

  • Con el -feager-blackholing-flag , los agujeros negros se crean en cambio tan pronto como un procesador comienza a evaluar, y la Guía del usuario recomienda esto si está haciendo un montón de paralelismo. Sin embargo, como el bloqueo en cada thunk sería demasiado caro, estos agujeros negros son más "ansiosos", que no están sincronizados con otros hilos (aunque otros hilos aún pueden verlos si no hay una condición de carrera). Solo cuando el hilo se detiene, estos se convierten en "verdaderos" agujeros negros.

  • Un tercer caso, sobre el cual la publicación de blog se trató en particular, se usa para funciones especiales como unsafePerformIO , para el cual es dañino evaluar un thunk más de una vez. En este caso, el hilo usa un agujero negro "verdadero" con bloqueo real, pero lo crea inmediatamente, insertando una pausa de hilo artificial antes de la evaluación real.

¿Cómo maneja GHC los thunk a los que acceden múltiples hilos (ya sean hilos explícitos o internos que evalúan las chispas)? ¿Puede suceder que varios hilos evalúen el mismo procesador, duplicando el trabajo? O, si los thunk están sincronizados, ¿cómo, para que el rendimiento no sufra?


Para resumir el artículo vinculado a en los comentarios: los thunks en GHC no son estrictamente atómicos entre múltiples hilos: es posible en una condición de carrera para que múltiples hilos evalúen el mismo thunk, duplicando el trabajo. Pero, esto no es un gran problema en la práctica porque:

  1. La pureza garantizada significa que nunca importa si un thunk se evalúa dos veces, en términos de semántica del programa. unsafePerformIO es un caso donde eso podría ser un problema, pero resulta que unsafePerformIO tiene cuidado de evitar volver a ejecutar la misma acción de E / unsafePerformIO
  2. Debido a que todos los valores son thunk, la mayoría de los thunk resultan ser bastante pequeños, por lo que ocasionalmente duplicar el trabajo para forzar uno no es un gran problema en términos de velocidad del programa. Puede imaginar que es caro duplicar, por ejemplo, el last [1,2..10000000] porque todo el cálculo es costoso. Pero, por supuesto, el thunk más externo simplemente resuelve otro thunk, algo así como:

    case [1,2..10000000] of [x] -> x (_:xs) -> last xs [] -> error "empty list"

    y si dos hilos duplican el trabajo para convertir la llamada a last uso, es bastante barato en el gran esquema de cosas.


Sí, a veces el mismo procesador puede ser evaluado por múltiples hilos. El tiempo de ejecución de GHC intenta minimizar la probabilidad de trabajo duplicado, por lo que en la práctica es raro. Consulte el documento "Haskell en un multiprocesador de memoria compartida" para obtener detalles de bajo nivel, en su mayoría la sección "Evaluación de procesador sin llave". (Recomendaría el papel para cada desarrollador profesional de Haskell por cierto).