Параллельное программирование с использованием Accelerate (Data.Array.Accelerate)
ситуация
В настоящее время я работаю над проектом, который занимается обнаружением краев. Поэтому я хотел бы рассчитать алгоритмы с использованием ускоренных массивов для достижения лучшей производительности. К сожалению, я довольно новичок в функциональном программировании, а также в параллельном программировании, и я действительно не знаю, как правильно поступить.
проблема
Чтобы преобразовать данное изображение в оттенки серого или даже выполнить обнаружение края, мне нужен доступ к каждому из пикселей / значений массива.
Используя неускоренные массивы (пакет Data.Array), я мог использовать оператор (!)- для получения желаемого значения.
Используя ускоренные массивы (пакет Data.Array.Accelerate), есть похожие функции, такие как..
(!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix -> Exp e
Описание: Форма выражения, извлекающая скаляр из массива.
(!!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int -> Exp e
Описание: Форма выражения, извлекающая скаляр из массива по линейному индексу
.. но они всегда заканчиваются возвращением значения выражения Accelerates (Exp e)
что приводит к моему вопросу..
Вопрос
Можно ли распаковать значение из Exp
тип данных или что бы вы порекомендовали мне сделать?
пример
Преобразование из изображения в ускоренный массив работает..
toArr :: Image PixelRGB8 -> Acc (Array DIM2 (Pixel8, Pixel8, Pixel8))
toArr img = use $ fromFunction (Z :. width :. height) (\(Z :. x :. y) -> let (PixelRGB8 r g b) = pixelAt img x y in (r, g, b))
where width = imageWidth img
height = imageHeight img
... но я не знаю, чтобы сделать это наоборот, потому что мне нужно было бы получить доступ к значению выражений, чтобы сгенерировать изображение из ширины / высоты / пикселей.
toJuicy :: Acc (Array DIM2 (Pixel8, Pixel8, Pixel8)) -> Image PixelRGB8
toJuicy arr = undefined
Любая помощь будет высоко оценен.
1 ответ
Важно подчеркнуть, что Accelerate
это не просто "обычное распараллеливание", а именно SIMD- распараллеливание, которое лучше всего работает на GPU. Но вы не можете просто считывать произвольные значения из памяти GPU, по крайней мере, не теряя при этом все преимущества в производительности, потому что эта память полностью не оптимизирована для произвольного доступа, а работает только в "пакетном режиме". Следовательно, функция библиотеки, которая выполняет реальную работу, всегда возвращает Acc
/ Exp
значение, поэтому промежуточные результаты могут фактически оставаться на GPU (или любом другом параллельном процессоре).
Теперь также возможно выполнить ускорение кода на процессоре, и в этом случае эта проблема на самом деле не возникает. Но даже здесь интерфейс поддерживается согласованным; Вы должны выполнить дорогостоящий расчет до конца и только в конце получить результаты обратно в "нормальные значения Хаскелла".
Чтобы выполнить этот поиск, каждый из специфичных для устройства бэкэндов предлагает run
функция, например Data.Array.Accelerate.LLVM.Native.run
,