Какие библиотеки следует использовать для улучшения потоковой обработки OCaml?
Я задал родственный вопрос до того, почему потоки OCaml считаются "недостаточно"?
Независимо от того, как "плохой" ocaml threading, я замечаю, что некоторые библиотеки говорят, что они могут делать настоящие потоки.
Например, сходница
Lwt предлагает новую альтернативу. Он обеспечивает очень легкие совлокальные потоки; "запуск" потока - очень быстрая операция, для него не требуется новый стек, новый процесс или что-то еще. Более того, коммутаторы контекста очень быстрые. На самом деле, так просто, что мы запустим поток для каждого системного вызова. И составление совлокальных потоков позволит нам писать высокоасинхронные программы.
Также Jane Street
aync_core также предоставляет похожие вещи, если я прав.
Но я совершенно смущен. Lwt
ли Lwt
или aync_core
потоки, такие как Java threading
?
Если я их использую, могу ли я использовать несколько процессоров?
Каким образом можно получить "реальную поточную" (как на Java) в OCaml?
редактировать
Я все еще смущен.
Позвольте мне добавить сценарий:
У меня есть сервер (16 cpu cores
) и серверное приложение.
Что делает серверное приложение:
- Он слушает запросы
- Для каждого запроса он запускает вычислительную задачу (скажем, стоит 2 минуты, чтобы закончить)
- Когда каждая задача заканчивается, задача будет либо вернуть результат обратно в основную, либо просто отправить результат обратно клиенту непосредственно
На Java это очень просто. Я создаю пул потоков, затем для каждого запроса я создаю поток в этом пуле. этот поток будет выполнять вычислительную задачу. Это зрелое Java, и оно может использовать 16 ядер процессора. Я прав?
Поэтому мой вопрос: могу ли я сделать то же самое в OCaml?
Ответы
Ответ 1
Пример параллелизированного сервера, который вы цитируете, является одной из тех проблемных проблем, которые хорошо решены с помощью простой многопроцессорной модели с использованием fork
. Это было сделано в OCaml на протяжении десятилетий, и да, вы будете почти линейным ускорением, используя все ядра вашей машины, если вам нужно.
Для этого, используя простые примитивы стандартной библиотеки, см. Эту главу онлайн-книги "Системное программирование Unix в OCaml" (впервые выпущен в 2003 году) и/или эту главу онлайн-книги "Разработка приложений с OCaml" (сначала выпущен в 2000 году).
Вы также можете использовать библиотеки более высокого уровня, такие как библиотеку Gerd Stolpmann OCamlnet, упомянутую rafix, которая предоставляет множество материалов из прямого помощника для обычного дизайна клиент/сервер, в библиотеки многопроцессорных коммуникаций более низкого уровня; см. документацию.
Библиотека Parmap также интересна, но, возможно, для немного другого варианта использования (более того, у вас есть большой массив данных, доступных одновременно, которые вы хотите обрабатывать с помощью одной и той же функции параллельно): переходная замена из Array.map
или List.map
(или fold
), который распараллеливает вычисления.
Ответ 2
Самое близкое, что вы найдете в реальной (превентивной) потоковой передаче, - это встроенная библиотека потоков. Под этим я имею в виду, что ваша модель программирования будет такой же, но с двумя важными отличиями:
- Собственные потоки OCaml не такие легкие, как Java.
- За один раз выполняется только один поток, поэтому вы не можете использовать несколько процессов.
Это делает потоки OCaml довольно плохим решением для параллелизма или параллелизма, поэтому в целом люди избегают их использования. Но у них все еще есть свои возможности.
Lwt и Async очень похожи и дают вам другой вкус резьбы - кооперативный стиль. Кооперативные потоки отличаются от превентивных в факте, что переключение между потоками явственно в коде, а блокирующие вызовы всегда очевидны из сигнатуры типа. Предоставляемые кооперативные потоки очень дешевы, так что они очень хорошо подходят для параллелизма, но снова не помогут вам с параллельными (из-за ограничений OCaml runtime).
См. Это для хорошего ознакомления с совместной резьбой: http://janestreet.github.io/guide-async.html
EDIT: для вашего конкретного сценария я бы использовал Parmap, если задачи настолько интенсивны в вычислительной мере, как в вашем примере, тогда накладные расходы на запуск процессов из parmap должны быть незначительными.