Используя clojure у меня есть очень большой объем данных в последовательности, и я хочу обработать его параллельно, с относительно небольшое количество ядер (4 - 8).
Самая легкая вещь сделать использовать pmap
вместо map
, для отображения моей обработки функционируют по последовательности данных. Но координация наверху приводит к чистому убытку в моем случае.
Я думаю, что причина - это pmap
предполагает, что функция, отображенная через данные, является очень дорогостоящей. При рассмотрении исходного кода pmap это, кажется, создает a future
для каждого элемента последовательности в свою очередь, таким образом, каждый вызов функции происходит на отдельном потоке (циклически повторяющийся по количеству доступных ядер).
Вот соответствующая часть источника pmap:
(defn pmap
"Like map, except f is applied in parallel. Semi-lazy in that the
parallel computation stays ahead of the consumption, but doesn't
realize the entire result unless required. Only useful for
computationally intensive functions where the time of f dominates
the coordination overhead."
([f coll]
(let [n (+ 2 (.. Runtime getRuntime availableProcessors))
rets (map #(future (f %)) coll)
step (fn step [[x & xs :as vs] fs]
(lazy-seq
(if-let [s (seq fs)]
(cons (deref x) (step xs (rest s)))
(map deref vs))))]
(step rets (drop n rets))))
;; multi-collection form of pmap elided
В моем случае отображенная функция не является настолько дорогой, но последовательность огромна (миллионы записей). Я думаю стоимость создания и разыменования, которое - много фьючерсов то, где параллельное усиление потеряно в издержках.
Мое понимание pmap
корректный?
Есть ли лучший шаблон в clojure для этого вида более низкой цены, но в широком масштабе повторенной обработки, чем pmap
? Я рассматриваю разделение на блоки последовательности данных так или иначе и затем выполнение потоков на больших блоках. Действительно ли это - разумный подход и какие clojure идиомы работали бы?
Этот вопрос: , как-эффективно - Apply-A-Medive-Weight-Function-Parallel также рассматривает эту проблему в очень аналогичном контексте.
Текущий лучший ответ - использовать раздел
, чтобы сломать его в куски. Затем PMAP функция карты на каждый кусок. Затем верните результаты. Стиль карты-уменьшения.
Вы можете использовать некоторые карты/сокращения, реализованные вручную. Также взгляните на структуру swarmiji .
«Распределенная вычислительная система, которая помогает писать и запускать код Clojure параллельно - между ядрами и процессорами»
К сожалению, не допустимый ответ, но что-то посмотреть в будущем, - это работа богатых с библиотекой Fork / Join, приходящая в Java 7. Если вы посмотрите на его филиал на Github, он сделал с ней работу и последним Я видел ранние доходы были потрясающими.
Пример богатых пробуя.