使用 Accelerate 的并行编程 (Data.Array.Accelerate)
Parallel Programming using Accelerate (Data.Array.Accelerate)
情况
目前我正在处理一个处理边缘检测的项目。因此,我想使用加速数组来计算算法以获得更好的性能。不幸的是,我对函数式编程和并行编程还很陌生,我真的不知道什么是正确的方法。
问题
要将给定图像转换为灰度甚至执行边缘检测,我需要访问数组的每个像素/值。
使用非加速数组(Data.Array 包)我可以使用 (!)-operator 来获得所需的值。
使用加速数组(Data.Array.Accelerate 包)有类似的功能,如..
(!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix -> Exp e
Description: Expression form that extracts a scalar from an array
(!!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int -> Exp e
Description: Expression form that extracts a scalar from an array at a linear index
.. 但他们总是以返回 Accelerates 的表达式值 (Exp e)
结束,这导致了我的问题..
问题
是否可以 'unpack' 来自 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
.. 但我不知道反之亦然,因为我需要访问表达式值才能从 width/height/pixels.
生成图像
toJuicy :: Acc (Array DIM2 (Pixel8, Pixel8, Pixel8)) -> Image PixelRGB8
toJuicy arr = undefined
非常感谢任何帮助。
需要强调的是,Accelerate
不仅仅是“正常并行化”——它特别是 SIMD 并行化,它在 GPU 上的效果最好。但是你不能只从 GPU 内存中读取任意值,至少不能在不失去所有性能优势的情况下这样做,因为该内存完全没有针对随机访问进行优化,而是只能在“批处理模式”下正常工作。因此,执行实际工作的库函数总是 return 一个 Acc
/ Exp
值,因此中间结果实际上可以保留在 GPU(或任何其他并行处理器)上。
现在,也可以在CPU上执行Accelerate代码,在这种情况下不会真正出现这个问题。但即使在这里,界面也保持一致;您应该将昂贵的计算进行到底,并且只在最后将结果检索回“正常 Haskell 值”。
为完成此检索,每个特定于设备的后端都提供了一个 run
函数,例如 Data.Array.Accelerate.LLVM.Native.run
。
情况
目前我正在处理一个处理边缘检测的项目。因此,我想使用加速数组来计算算法以获得更好的性能。不幸的是,我对函数式编程和并行编程还很陌生,我真的不知道什么是正确的方法。
问题
要将给定图像转换为灰度甚至执行边缘检测,我需要访问数组的每个像素/值。
使用非加速数组(Data.Array 包)我可以使用 (!)-operator 来获得所需的值。
使用加速数组(Data.Array.Accelerate 包)有类似的功能,如..
(!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix -> Exp e
Description: Expression form that extracts a scalar from an array
(!!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int -> Exp e
Description: Expression form that extracts a scalar from an array at a linear index
.. 但他们总是以返回 Accelerates 的表达式值 (Exp e)
结束,这导致了我的问题..
问题
是否可以 'unpack' 来自 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
.. 但我不知道反之亦然,因为我需要访问表达式值才能从 width/height/pixels.
生成图像toJuicy :: Acc (Array DIM2 (Pixel8, Pixel8, Pixel8)) -> Image PixelRGB8
toJuicy arr = undefined
非常感谢任何帮助。
需要强调的是,Accelerate
不仅仅是“正常并行化”——它特别是 SIMD 并行化,它在 GPU 上的效果最好。但是你不能只从 GPU 内存中读取任意值,至少不能在不失去所有性能优势的情况下这样做,因为该内存完全没有针对随机访问进行优化,而是只能在“批处理模式”下正常工作。因此,执行实际工作的库函数总是 return 一个 Acc
/ Exp
值,因此中间结果实际上可以保留在 GPU(或任何其他并行处理器)上。
现在,也可以在CPU上执行Accelerate代码,在这种情况下不会真正出现这个问题。但即使在这里,界面也保持一致;您应该将昂贵的计算进行到底,并且只在最后将结果检索回“正常 Haskell 值”。
为完成此检索,每个特定于设备的后端都提供了一个 run
函数,例如 Data.Array.Accelerate.LLVM.Native.run
。