Параллельное программирование с использованием 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,

Другие вопросы по тегам