Я выполнял некоторые вычислительные работы в F#. Такие функции, как Array.Parallel.map
, использующие.Net Task Parallel Library, экспоненциально ускорили мой код, затрачивая минимум усилий.
Однако из-за проблем с памятью я переделал часть своего кода так, чтобы его можно было лениво вычислять внутри выражения последовательности (, это означает, что мне нужно хранить и передавать меньше информации). Когда пришло время оценить, я использовал:
// processor and memory intensive task, results are not stored
let calculations : seq = seq {...yield one thing at a time... }
// extract results from calculations for summary data
PSeq.iter someFuncToExtractResults results
вместо :
// processor and memory intensive task, storing these results is an unnecessary task
let calculations : Calculation[] =...do all the things...
// extract results from calculations for summary data
Array.Parallel.map someFuncToExtractResults calculations
. При использовании любой из функций Array.Parallel я ясно вижу, что все ядра моего компьютера включаются в работу (~100% загрузка ЦП). Однако требуемая дополнительная память означает, что программа никогда не завершалась.
С версией PSeq.iter, когда я запускаю программу, загрузка ЦП составляет всего около 8% (и минимальное использование ОЗУ).
Итак:Есть ли какая-то причина, по которой версия PSeq работает намного медленнее? Это из-за ленивой оценки? Есть ли какой-то волшебный материал «быть параллельным», который мне не хватает?
Спасибо,
Другие ресурсы, реализации исходного кода обоих (кажется, что они используют разные параллельные библиотеки в.NET):
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/array.fs
https://github.com/fsharp/powerpack/blob/master/src/FSharp.PowerPack.Parallel.Seq/pseq.fs
ИЗМЕНИТЬ :Добавлены дополнительные подробности в примеры кода и подробности
Код:
Seq
// processor and memory intensive task, results are not stored
let calculations : seq =
seq {
for index in 0..data.length-1 do
yield calculationFunc data.[index]
}
// extract results from calculations for summary data (different module)
PSeq.iter someFuncToExtractResults results
Array
// processor and memory intensive task, storing these results is an unnecessary task
let calculations : Calculation[] =
Array.Parallel.map calculationFunc data
// extract results from calculations for summary data (different module)
Array.Parallel.map someFuncToExtractResults calculations
Details: