Сколько потоков порождает функция pmap Clojure для операций выборки URL? - PullRequest
21 голосов
/ 16 февраля 2011

Документация по функции pmap заставляет меня задуматься о том, насколько эффективной она будет для чего-то вроде извлечения коллекции XML-каналов через Интернет.Я понятия не имею, сколько параллельных операций выборки будет порождать pmap и каков будет максимальный размер.

Ответы [ 4 ]

21 голосов
/ 17 февраля 2011

Если вы проверите источник, который вы видите:

> (use 'clojure.repl)
> (source 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."
  {:added "1.0"}
  ([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))))
  ([f coll & colls]
   (let [step (fn step [cs]
                (lazy-seq
                 (let [ss (map seq cs)]
                   (when (every? identity ss)
                     (cons (map first ss) (step (map rest ss)))))))]
     (pmap #(apply f %) (step (cons coll colls))))))

(+ 2 (.. Runtime getRuntime availableProcessors)) является большой подсказкой.pmap захватит первые (+ 2 processors) фрагменты работы и выполнит их асинхронно через future.Так что, если у вас есть 2 ядра, он будет запускать 4 работы одновременно, пытаясь немного опередить вас, но максимум должен быть 2 + n.

future в конечном итоге использует агент/ O поток пулов, который поддерживает неограниченное количество потоков.Он будет расти по мере выполнения работы и сокращаться, если нити не используются.

11 голосов
/ 17 февраля 2011

Основываясь на превосходном ответе Алекса, который объясняет, как работает pmap, вот мое предложение для вашей ситуации:

(doall
  (map
    #(future (my-web-fetch-function %))
    list-of-xml-feeds-to-fetch))

Обоснование:

  • Вам нужно как можно больше работ в полете, поскольку большинство из них блокирует сетевой ввод-вывод.
  • Future будет запускать асинхронную часть работы для каждого запроса, который будет обрабатываться в пуле потоков. Вы можете позволить Clojure позаботиться об этом разумно.
  • Обстановка на карте вызовет оценку полной последовательности (т. Е. Запуск всех запросов).
  • Ваш основной поток может сразу же начать разыменование фьючерса и, следовательно, может продолжать прогрессировать по мере возвращения отдельных результатов
3 голосов
/ 22 февраля 2011

Нет времени писать длинный ответ, но есть http-агент clojure.contrib, который создает каждый запрос на получение / публикацию в качестве своего собственного агента.Таким образом, вы можете выполнить тысячу запросов, и все они будут работать параллельно и завершаться по мере поступления результатов.

1 голос
/ 04 апреля 2014

Глядя на работу pmap, кажется, что одновременно идет 32 потока, независимо от того, сколько у вас процессоров, проблема в том, что карта опередит вычисления на 32, и фьючерсы будут запущены самостоятельно.(ОБРАЗЕЦ) (defn samplef [n] (println "starting " n) (Thread/sleep 10000) n) (def result (pmap samplef (range 0 100)))

;вы будете ждать в течение 10 секунд и увидите 32 отпечатка, затем, когда вы возьмете 33-й и другие 32;печатает в эти минуты, что вы выполняете 32 одновременных потока одновременно;для меня это не идеально;SALUDOS Felipe

...