在我最近的工作中Gibbs sampling,我一直在充分利用RVar它,在我看来,它为随机数生成提供了一个近乎理想的界面.遗憾的是,由于无法在地图中使用monadic动作,我无法使用Repa.
虽然一般来说明显的monadic地图不能并行化,但在我看来,这RVar可能至少是monad的一个例子,其中效果可以安全地并行化(至少在原则上;我对内部工作原理并不十分熟悉RVar) .也就是说,我想写下面的内容,
drawClass :: Sample -> RVar Class
drawClass = ...
drawClasses :: Array U DIM1 Sample -> RVar (Array U DIM1 Class)
drawClasses samples = A.mapM drawClass samples
Run Code Online (Sandbox Code Playgroud)
这里A.mapM看起来是这样的,
mapM :: ParallelMonad m => (a -> m b) -> Array r sh a -> m (Array r sh b)
Run Code Online (Sandbox Code Playgroud)
虽然这显然是如何工作的,但关键取决于其实现RVar及其基础RandomSource,原则上人们会认为这将涉及为每个产生的线程绘制一个新的随机种子并照常进行.
直觉上,似乎同样的想法可能会推广到其他一些monad.
所以,我的问题是:是否可以构建一个ParallelMonadmonad 类,其效果可以安全地并行化(可能至少有人居住RVar)?
它看起来像什么?还有哪些monad可能会在这个课程中出现?还有其他人考虑过如何在维修中使用它的可能性吗?
最后,如果并行monadic动作的这个概念不能概括,那么有没有人看到任何好的方法来使这个工作在特定的情况下RVar(它将非常有用)?放弃 …
我发现数组库Repa for Haskell非常有趣,并且想要制作一个简单的程序,试图了解如何使用它.我还使用列表进行了简单的实现,事实证明它更快.我的主要问题是如何改进下面的Repa代码以使其最有效(并且希望也非常易读).我是一个很新的使用Haskell,我找不到任何容易理解的关于Repa的教程[ 在Haskell Wiki上编辑一个,我在写这篇文章的时候有点忘记],所以不要以为我什么都知道.:)例如,我不确定何时使用force或deepSeqArray.
该程序用于以下列方式近似计算球体的体积:
下面显示了两个版本,一个使用列表,另一个使用repa.我知道代码是低效的,特别是对于这个用例,但是想法是让它在以后变得更复杂.
对于下面的值,并使用"ghc -Odph -fllvm -fforce-recomp -rtsopts -threaded"进行编译,列表版本需要1.4秒,而修复版本需要12秒,+ RTS -N1和10秒+ + RTS - N2,虽然没有转换火花(我有一台双核Intel机器(Core 2 Duo E7400 @ 2.8 GHz)运行Windows 7 64,GHC 7.0.2和llvm 2.8).(注释下面主要的正确行,只运行其中一个版本.)
感谢您的任何帮助!
import Data.Array.Repa as R
import qualified Data.Vector.Unboxed as V
import Prelude as P
-- Calculate the volume of a sphere by putting it in a bath of coordinates. Generate coordinates (x,y,z) in a cuboid. Then, for each coordinate, check if it is inside the …Run Code Online (Sandbox Code Playgroud) 假设我想使用有限差分法对一个看涨期权定价,然后修复以下工作:
import Data.Array.Repa as Repa
r, sigma, k, t, xMax, deltaX, deltaT :: Double
m, n, p :: Int
r = 0.05
sigma = 0.2
k = 50.0
t = 3.0
m = 3
p = 1
xMax = 150
deltaX = xMax / (fromIntegral m)
n = 800
deltaT = t / (fromIntegral n)
singleUpdater a = traverse a id f
where
Z :. m = extent a
f _get (Z :. ix) | ix == 0 = 0.0 …Run Code Online (Sandbox Code Playgroud) 文档说,
有时您想要在GHC的管道中准确控制INLINE编译指示何时打开.
我为什么要这个?(除非我也使用RULES编译指示,在这种情况下,我可能希望推迟函数的内联,以便触发相关规则.)只有在简化过程的特定阶段才能更好地内联哪些函数?
我已经开发了一个累积和函数,如下面在Haskell库Repa中定义的那样.但是,在将此函数与转置操作组合时,我遇到了一个问题.以下所有3项操作都在一秒钟内完成:
cumsum $ cumsum $ cumsum x
transpose $ transpose $ transpose x
transpose $ cumsum x
Run Code Online (Sandbox Code Playgroud)
但是,如果我写:
cumsum $ transpose x
Run Code Online (Sandbox Code Playgroud)
性能骇人听闻.虽然单独的每个操作在1920x1080图像上都不到一秒钟,但当它们合并时,它们现在需要30秒以上......
关于可能导致这种情况的任何想法?我的直觉告诉我它与延迟阵列有关,而不是在正确的时间强迫等等......但是我还没有足够的经验去追踪它.
{-# LANGUAGE TypeOperators, FlexibleContexts, TypeFamilies #-}
import Data.Array.Repa as Repa
{-# INLINE indexSlice #-}
indexSlice :: (Shape sh, Elt a) => Int -> Array (sh :. Int) a -> (sh :. Int) -> a
indexSlice from arr (z :. ix) = arr `unsafeIndex` (z :. (ix + from))
{-# INLINE sliceRange #-}
sliceRange :: (Slice sh, …Run Code Online (Sandbox Code Playgroud) 我想在标准数组包中实现类似于有界数组的东西,但是使用了数组.
实现这一目标的好方法是什么?
这是我尝试过的,但必须有一个比检查边界的自定义函数中包装所有内容更好的方法:
import Data.Array.Repa
data C = A | F | L deriving (Eq,Enum,Ord,Bounded,Show)
data Ballot c = Ballot {
vote::Array U (Z :. Int) Int
} deriving Show
mkBallot::(Eq c ,Enum c,Ord c, Bounded c, Show c) => c -> Ballot c
mkBallot c = Ballot $ fromListUnboxed (Z :. max) (genSc c)
where
max = (fromEnum (maxBound `asTypeOf` c)) + 1
genSc::(Eq c,Enum c,Ord c,Bounded c,Show c) => c -> [Int]
genSc c = [ f x …Run Code Online (Sandbox Code Playgroud) 在Repa中,我想d在我的数组的最内层维度上并行应用一定的线性变换,即在所有"列"向量上.
通常,这样的变换可以表示为一个矩阵M,并且各条目M*v只是适当的行的点积M用v.所以我可以使用traverse一个计算相应点积的函数.这需要付出代价d^2.
但是,我M很特别:它承认了线性工作顺序算法.例如,M可能是1整个下三角形中具有s的下三角矩阵.然后M*v只是部分和的向量v(又名"扫描").这些总和可以以显而易见的方式顺序计算,但是需要结果的(i-1)st条目来i有效地计算该条目.(我有几个这样的M,所有这些都可以在线性顺序时间内以一种方式计算.)
我没有看到任何明显的使用方法traverse(或任何其他的维修功能)来利用这个属性M.可以吗?d^2当有如此快速的线性工作算法时,使用工作算法(即使具有丰富的并行性)将是非常浪费的.
(我看过一些旧的SO帖子(例如,这里)提出类似的问题,但没有什么能与我的情况相符.)
UPDATE
根据请求,这里是一些说明性代码,用于M计算部分和(如上所述).正如我所料,运行时(work)以超线性方式增长d,即array(ext)范围的第二个参数.这来自于这样的事实:mulM'仅指定如何计算i输出的条目,而与所有其他条目无关.即使在阵列的总大小中存在线性时间算法,我也不知道如何在Repa中表达它.
有趣的是,如果删除定义该清单中的线array'从main,则运行时仅线性比例在所述阵列的总大小!因此,当数组被"一直向下"延迟时,融合/优化必须以某种方式提取线性工作算法,但没有任何明确的帮助.这太棒了,但对我来说也不是很有用,因为实际上我需要调用mulM清单数组.
{-# LANGUAGE TypeOperators, ScopedTypeVariables, FlexibleContexts #-}
module Main where
import Data.Array.Repa as R
-- multiplication by M across …Run Code Online (Sandbox Code Playgroud) 我一直在玩修复和加速 - 他们都很有趣,但是当我使用一个而另一个时,我无法解决问题.他们在一起成长,竞争对手,还是仅仅针对不同的问题?
这里有一个基本的monad问题,与Repa无关,还有几个与Repa有关的问题.
我正在使用Repa3工作.我无法获得高效的并行代码.如果我让我的函数返回延迟数组,我会得到极其缓慢的代码,可以很好地扩展到8个内核.该代码每GHC探测器占用超过20GB的内存,并且比基本的Haskell未装箱矢量运行几个数量级.
或者,如果我让所有函数返回Unboxed清单数组(仍然尝试在函数中使用fusion,例如当我执行'map')时,我获得了更快的代码(仍然比使用Haskell未装箱的向量慢)根本没有扩展,实际上随着核心数量的增加会略微变慢.
基于Repa-Algorithms中的FFT示例代码,似乎正确的方法是始终返回清单数组.有没有我应该返回延迟数组的情况?
FFT代码也充分利用了'now'功能.但是,当我尝试在我的代码中使用它时,我收到类型错误:
type Arr t r = Array t DIM1 r
data CycRingRepa m r = CRTBasis (Arr U r)
| PowBasis (Arr U r)
fromArray :: forall m r t. (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r
fromArray =
let mval = reflectNum (Proxy::Proxy m)
in \x ->
let sh:.n = extent x
in assert (mval == 2*n) PowBasis $ now $ computeUnboxedP $ bitrev x
Run Code Online (Sandbox Code Playgroud)
没有'now',代码编译得很好.使用'now',我收到以下错误: …
haskell ×10
repa ×10
arrays ×5
performance ×4
profiling ×2
ghc ×1
inlining ×1
monads ×1
sequential ×1