【问题标题】:Repa nested array definitions resulting in "Performing nested parallel computation sequentially..."Repa 嵌套数组定义导致“按顺序执行嵌套并行计算...”
【发布时间】:2012-01-03 02:37:26
【问题描述】:

作为一个更大问题的一部分,我试图在数组中定义一个数组,如下所示:

import Data.Array.Repa
type Arr = Array DIM2 Int

arr = force $ fromList (Z :. 5 :. 5) [1..25] :: Arr

combined :: Arr
combined = arr `deepSeqArray` 
    traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) (\f (Z :. x :. y) -> 
        let reg = force $ extract f (x,y) (2,2)
        in  reg `deepSeqArray` sumAll reg)

extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Arr
extract lookup (x0,y0) (width,height) = fromFunction bounds 
  $ \sh -> offset lookup sh
    where 
    bounds = Z :. width :. height
    offset :: (DIM2 -> Int) -> DIM2 -> Int
    offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0)

main = print combined

extract 函数使用fromFunction 和提供给它的查找函数,但它也可以使用traversearr ! ... 达到相同的效果。尽管尽可能早地到处使用forcedeepSeqArray,但控制台在这里填满了消息,然后是正确的结果:

Data.Array.Repa:按顺序执行嵌套并行计算。 您可能已经调用了“强制”函数,而另一个实例是 已经运行。如果第二个版本因暂停而发生这种情况 懒惰的评价。使用“deepSeqArray”确保每个数组都完全 在“强制”下一个之前进行评估。

虽然我还没有构建一个带有列表来比较速度的版本,但在较大的版本中性能会受到影响。

这仅仅是嵌套数组定义的结果,因此我应该重组我的程序以将内部或外部定义变为列表吗?我的extract 功能是否很糟糕以及问题的原因?

from this question 的提示非常有用,但我还没有爬过编译的代码。

【问题讨论】:

    标签: haskell repa


    【解决方案1】:

    这是因为'print' 也隐式地强制数组。内部的“force”和“sumAll”函数调用并行计算,但执行“print”,所以你有嵌套的并行性。如此不明显的事实是 Repa 2 API 的一大遗憾。

    Repa 3 通过导出 'force' 和 'sumAll' 等的顺序和并行版本来解决这些问题。它还在数组类型中添加了一个标签,以指示数组是延迟还是清单。 Repa 3 尚未完成,但您可以在 http://code.ouroborus.net/repa 上使用 head 版本。它应该会在今年晚些时候的 GHC 7.4 之后发布。

    这是您的示例的 Repa 3 版本,它在运行时不会发出有关嵌套并行性的警告。请注意,“力”现在是“计算”。

    import Data.Array.Repa
    
    arr :: Array U DIM2 Int
    arr = fromListUnboxed (Z :. 5 :. 5) [1..25]
    
    combined :: Array U DIM2 Int
    combined 
      = computeP $ traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) 
      $ \f (Z :. x :. y) -> sumAllS $ extract f (x,y) (2,2)
    
    extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Array D DIM2 Int
    extract lookup (x0,y0) (width,height) 
      = fromFunction bounds 
      $ \sh -> offset lookup sh
        where 
        bounds = Z :. width :. height
        offset :: (DIM2 -> Int) -> DIM2 -> Int
        offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0)
    
    main = print combined
    

    【讨论】:

      猜你喜欢
      • 2016-01-04
      • 2020-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      • 2021-08-11
      相关资源
      最近更新 更多