使用 Accelerate 进行并行编程 (Data.Array.Accelerate)

Posted

技术标签:

【中文标题】使用 Accelerate 进行并行编程 (Data.Array.Accelerate)【英文标题】:Parallel Programming using Accelerate (Data.Array.Accelerate) 【发布时间】:2017-10-09 14:36:49 【问题描述】:

情况 目前我正在研究一个处理边缘检测的项目。因此,我想使用加速数组来计算算法以获得更好的性能。不幸的是,我对函数式编程以及并行编程还是很陌生,我真的不知道什么是正确的方法。

问题 要将给定的图像转换为灰度甚至执行边缘检测,我需要访问数组的每个像素/值。

使用非加速数组(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(或任何其他并行处理器)上。

现在,也可能在 CPU 上执行 Accelerate 代码,在这种情况下,这个问题不会真正出现。但即使在这里,界面也保持一致;您应该执行到最后的昂贵计算,并且仅在最后将结果检索回“正常的 Haskell 值”。

为了完成这种检索,每个特定于设备的后端都提供了一个run 函数,例如Data.Array.Accelerate.LLVM.Native.run

【讨论】:

以上是关于使用 Accelerate 进行并行编程 (Data.Array.Accelerate)的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 使用 Accelerate.framework 对向量进行按位异或

Objective-C - 使用 Accelerate.framework 对两个矩阵进行元素加法(和除法)

Accelerate 的 vImage 与 vDSP

Accelerate框架的最小二乘函数?

使用 APScheduler 在 python 中进行并行编程的最佳方法是啥?

使用pthread进行并行编程