В вашем вопросе есть несколько аспектов.
Ключевым справочным материалом для проектных решений в среде выполнения GHC является документ '' Поддержка времени выполнения для Multicore Haskell '' .
Напомним, что
Система выполнения GHC поддерживает миллионы легких потоков
путем мультиплексирования их в несколько потоков операционной системы,
примерно по одному на каждый физический процессор.
И
Каждый поток Haskell работает в стеке конечного размера, который расположен в
куча Состояние потока вместе со своим стеком сохраняется в
выделенный в куче объект состояния потока (TSO). Размер TSO составляет около
15 слов плюс стек и составляют все состояние Haskell
нить. Стек может расти, копируя TSO в большую область, и
может впоследствии снова сжиматься
GHC не компилируется через CPS. Каждый поток делает рекурсивные вызовы, и они должны выделяться стеку. Представляя стек как объект, выделенный в куче, все становится проще.
Нить - это больше, чем замыкание.
По мере выполнения потока он начинает выделять кучу и стек. Таким образом:
Стек потока, а следовательно, и его TSO, является изменяемым. Когда
поток выполняется, стек будет накапливать указатели на новые объекты,
и поэтому, если TSO находится в старом поколении, оно должно быть добавлено к
запомненный набор [ГК].
Объекты сбора мусора, на которые указывают стеки, можно оптимизировать, чтобы обеспечить сборку мусора в том же физическом потоке, что и поток.
Кроме того, когда работает сборщик мусора,
очень желательно, чтобы TSO, которые были выполнены на
данный ЦП проходит сборщик мусора на том же ЦП,
потому что TSO и данные, на которые он ссылается, скорее всего, будут находиться в местном
кеш этого процессора.
Итак, GHC имеет стек для каждого потока, потому что компиляция требует, чтобы потоки имели доступ к стеку и куче. Предоставляя каждому потоку свой собственный стек, потоки могут работать параллельно более эффективно. Потоки - это больше, чем просто замыкание, поскольку они имеют изменяемый стек.