Ответ 1
Как использовать функцию partition
для разбивки последовательности range
? Был интересный пост по аналогичной проблеме в http://www.fatvat.co.uk/2009/05/jvisualvm-and-clojure.html
Я хочу сопоставить скромно дорогостоящую функцию на большом ленивом seq параллельно. pmap
отлично, но я теряю много переключение контекста. Я думаю, мне нужно увеличить размер куска работы, который передается каждому потоку.
Я написал о функции разбить seq на куски и pmap функцию на каждый кусок и рекомбинировать их. это "работает", но результаты не были впечатляющими. Исходный код по существу выглядит следующим образом:
(pmap eval-polynomial (range x) coificients)
Как я могу на самом деле сжать это, сохраняя его ленивым?
Как использовать функцию partition
для разбивки последовательности range
? Был интересный пост по аналогичной проблеме в http://www.fatvat.co.uk/2009/05/jvisualvm-and-clojure.html
Я бы посмотрел на функцию ppmap: http://www.braveclojure.com/zombie-metaphysics/. Он позволяет вам pmap при задании размера куска.
Решение этой проблемы заключается в увеличении размера зерна или объем работы, выполняемой каждой параллелизированной задачей. В этом случае задача заключается в применении функции отображения к одному элементу коллекции. Размер зерна не измеряется ни в одной стандартной единице, но вы говорите, что размер зерна pmap по умолчанию равен единице. Увеличение размера зерна до двух будет означать, что вы применяете функцию отображения к двум элементам вместо одного, поэтому поток, на котором выполняется эта задача, делает больше работы. [...] Просто для удовольствия мы можем обобщить эту технику на функцию ppmap, для разбитого pmap. Он может принимать более одного сбор, как карта:
(defn ppmap
"Partitioned pmap, for grouping map ops together to make parallel
overhead worthwhile"
[grain-size f & colls]
(apply concat
(apply pmap
(fn [& pgroups] (doall (apply map f pgroups)))
(map (partial partition-all grain-size) colls))))
(time (dorun (ppmap 1000 clojure.string/lower-case orc-name-abbrevs)))
; => "Elapsed time: 44.902 msecs"
Если вы не против чего-то слегка экзотического (в обмен на какое-то действительно заметное ускорение), вы можете также захотеть заглянуть в работу, проделанную автором Penumbra-библиотеки, которая обеспечивает легкий доступ к графическому процессору.
Я бы посмотрел на библиотеку Fork/Join, которая будет интегрирована в JDK 7. Это легкая модель потоковой передачи, оптимизированная для неблокирования, вычислять деление и побеждать над набором данных, используя пул потоков, планировщик работы и зеленые потоки.
Проделана некоторая работа, чтобы обернуть API Fork/Join в par, но он не был объединен в main (пока).