Ответ 1
Из сообщение в блоге связанный @Lambdageek, Комментарий GHC и Руководство пользователя GHC Я собираю следующее:
GHC пытается предотвратить переоценку thunks, но поскольку истинная блокировка между потоками является дорогостоящей, а thunks обычно чисты и настолько безвредны для переоценки, она обычно делает это небрежно, с небольшой вероятностью дублирования работы в любом случае.
Метод, который он использует для избежания работы, заключается в замене thunks черной дырой, специальным маркером, который сообщает другим потокам (или иногда самому потоку, как это происходит при обнаружении <<loop>>
), которое оценивается thunk.
Учитывая это, существует как минимум три варианта:
-
По умолчанию он использует "ленивый черный чекхолдинг", где это делается только до того, как поток вот-вот остановится. Затем он "ходит" по своему стеку и создает "истинные" черные дыры для новых трюков, используя блокировку, чтобы гарантировать, что каждый поток получает только один поток, зачерпывающий его, и прервать собственную оценку, если обнаруживает другой поток, уже зачерпнул thunk. Это дешевле, так как не нужно рассматривать трюки, чье время оценки настолько короткое, что оно полностью совпадает между двумя паузами.
-
С помощью
-feager-blackholing-flag
вместо этого создаются черные дыры, как только начнется оценка thunk, и в Руководстве пользователя рекомендуется это, если вы делаете много parallelism. Однако, поскольку блокировка на каждом thunk будет слишком дорогой, эти черные дыры являются более дешевыми "нетерпеливыми", которые не синхронизируются с другими потоками (хотя другие потоки все еще могут видеть их, если нет состояния гонки). Только когда потоки приостанавливаются, они превращаются в "истинные" черные дыры. -
Третий случай, о котором особенно беспокоился блог, используется для специальных функций, таких как
unsafePerformIO
, для которых вредно оценивать thunk более одного раза. В этом случае поток использует "истинную" черную дыру с реальной блокировкой, но создает ее немедленно, вставляя искусственную нить в паузу перед реальной оценкой.