1

不幸的是,整个示例涉及大量代码。你可以在这里看到完整的模块(仍然无法编译),下面的伪代码函数 f 对应于 hpaste 中的 'FIXME' 标签。

这是一个伪代码大纲:

module Test (run) where
    import Data.Vector.Unboxed as U

    run m i iters = let {get q} in do print $ testWrapper iters m q

    testWrapper :: forall i . Int -> Int -> i -> U.Vector i
    testWrapper iters m q =
        let {get test params: xs, dim, ru}
        in U.map fromIntegral (iterate (f dim ru) xs !! iters)

    {-# INLINE f #-}
    f :: (Int, Int) -> Vector r -> Vector r -> Vector r
    f dim ru = (g dim ru) . zipWith (*) ru

    {-# INLINE g #-}
    g :: (Int, Int) -> Vector r -> Vector r -> Vector r
    g dim ru = ...

对于某些参数,此代码在 ~.5 秒内运行。

我还测试了将 f 更改为 f':

f' dim ru = (g dim ru)

(我只是删除了最终的 zipWith,减少了所需的整体工作)。

在相同的输入参数上,修改后的代码需要 4.5 秒。

这发生在使用 optimizaiton 编译(使用 GHC 7.4.2、ghc -O2 以及更多优化)时。快速版本的核心大约是 3000 行,而慢版本的核心大约是 1900 行。

这可能没什么可做的,但是什么样的 GHC 疯狂可能会导致我的程序通过减少它所做的工作而减速一个数量级?当我最小的测试用例基本上生成超过 2000 行核心时,我怎么会发现这样的东西

谢谢

4

1 回答 1

3

查看堆配置文件。会不会是“更少的工作”版本留下了一些未评估的 thunk?这会导致较大的内存占用,并通过垃圾收集影响速度。

于 2013-02-10T20:46:31.737 回答