Легкие потоки Haskell накладные расходы и использование на многоядерных

Я читал книгу "Real World Haskell", главу о параллелизме и параллелизме. Мой вопрос заключается в следующем:

  • Поскольку потоки Haskell на самом деле представляют собой просто несколько "виртуальных" потоков внутри одного "реального" потока ОС, означает ли это, что их создание (например, 1000) не окажет существенного влияния на производительность? Т.е. можем ли мы сказать, что накладные расходы, понесенные при создании потока Haskell с forkIO является (почти) незначительным? Пожалуйста, приведите практические примеры, если это возможно.

  • Разве концепция легких потоков не мешает нам использовать преимущества многоядерных архитектур? Как я понимаю, два потока Haskell не могут выполняться одновременно на двух отдельных ядрах, потому что они действительно являются одним потоком с точки зрения операционной системы. Или среда выполнения Haskell делает некоторые хитрые трюки, чтобы гарантировать возможность использования нескольких процессоров?

3 ответа

Решение

Среда выполнения GHC обеспечивает среду исполнения, поддерживающую миллиарды искр, тысячи легких потоков, которые могут быть распределены по нескольким аппаратным ядрам. Компилировать с -threaded и использовать +RTS -N4 флаги для установки желаемого количества ядер.

искр / нити / работники / сердечники

В частности:

Означает ли это, что создание многих из них (например, 1000) не окажет существенного влияния на производительность?

Что ж, создание 1 000 000 из них, безусловно, возможно. 1000 так дешево, что даже не появится. В тестах создания потоков, таких как "Thread Ring", вы можете видеть, что GHC очень, очень хорош.

Разве концепция легких потоков не мешает нам использовать преимущества многоядерных архитектур?

Не за что. GHC работает на многоядерных процессорах с 2004 года. Текущее состояние многоядерной среды выполнения отслеживается здесь.

Как это сделать? Лучшее место, чтобы прочитать об этой архитектуре - статья "Поддержка времени выполнения для Multicore Haskell":

Система времени выполнения GHC поддерживает миллионы облегченных потоков, объединяя их в несколько потоков операционной системы, примерно по одному на каждый физический процессор....

Потоки Haskell выполняются набором потоков операционной системы, которые мы называем рабочими потоками. Мы поддерживаем примерно один рабочий поток на физический процессор, но какой именно рабочий поток может меняться от момента к моменту...

Поскольку рабочий поток может измениться, мы поддерживаем ровно один контекст выполнения Haskell (HEC) для каждого процессора. HEC - это структура данных, которая содержит все данные, которые требуются рабочему потоку ОС для выполнения потоков Haskell.

Вы можете следить за тем, как создаются ваши потоки и где они выполняются, с помощью нитей., Вот, например, запуск теста бинарных деревьев:

threadscope

  • Веб-сервер Warp широко использует эти легкие потоки, чтобы получить действительно хорошую производительность. Обратите внимание, что другие веб-серверы на Haskell также порождают конкуренцию: это скорее "Haskell хорош", чем "Warp хорош".

  • Haskell предоставляет многопоточную среду выполнения, которая может распределять легкие потоки по нескольким системным потокам. Он работает очень хорошо до 4 ядер. Помимо этого, есть некоторые проблемы с производительностью, хотя над ними активно ведутся работы.

Создание 1000 процессов - это относительно легкий вес; не беспокойся об этом. Что касается производительности, вы должны просто сравнить ее.

Как было указано ранее, несколько ядер работают просто отлично. Несколько потоков Haskell могут работать одновременно, будучи запланированными в разных потоках ОС.

Другие вопросы по тегам