Как эффективно применять функцию среднего веса параллельно
Я пытаюсь отобразить скромно дорогую функцию на большой ленивый seq параллельно. pmap
это здорово, но я проигрываю многим из-за переключения контекста. Я думаю, что мне нужно увеличить размер работы, передаваемой каждому потоку.
Я написал функцию, которая разбивает последовательность на части и помещает функцию в каждую часть и объединяет их. это "работает", но результаты не были впечатляющими. Оригинальный код по сути выглядит так:
(pmap eval-polynomial (range x) coificients)
Как я могу действительно сжать это, сохраняя это ленивым?
4 ответа
Как насчет использования 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. Это легкая модель потоков, оптимизированная для неблокирующих вычислений, вычислений типа "разделяй и властвуй" над набором данных, с использованием пула потоков, планировщика кражи работ и зеленых потоков.,
Некоторая работа была проделана, чтобы обернуть Fork/Join API в ветку par, но она еще не была объединена с main ( пока).