Я хочу написать функцию параллельной карты в Haskell, которая будет максимально эффективной. Моя первоначальная попытка, которая кажется наилучшей в настоящее время, состоит в том, чтобы просто написать:
pmap :: (a -> b) -> [a] -> [b]
pmap f = runEval . parList rseq . map f
Однако я не вижу идеального деления процессора. Если это, возможно, связано с количеством искр, могу ли я написать pmap, которое делит список на # процессорных сегментов, поэтому создаются минимальные искры? Я попробовал следующее, но производительность (и количество искр) намного хуже,
pmap :: (a -> b) -> [a] -> [b]
pmap f xs = concat $ runEval $ parList rseq $ map (map f) (chunk xs) where
-- the (len / 4) argument represents the size of the sublists
chunk xs = chunk' ((length xs) `div` 4) xs
chunk' n xs | length xs <= n = [xs]
| otherwise = take n xs : chunk (drop n xs)
Худшая производительность может быть связана с более высоким использованием памяти. Исходный pmap действительно немного масштабируется на 24-ядерных системах, поэтому у меня недостаточно данных.
(Количество процессоров на моем рабочем столе равно 4, поэтому я просто запрограммировал это).
Редактировать 1
Некоторые данные о производительности, использующие +RTS -H512m -N -sstderr -RTS
, находятся здесь: