Haskell 在repa算法函数中观察到意外性能
我正在用以下代码测试Haskell 在repa算法函数中观察到意外性能,haskell,repa,Haskell,Repa,我正在用以下代码测试repa-algorithms-3.2.1.1中的mmultP函数(为了简洁起见,这里有一点压缩): 以下是线程运行时中的顺序运行: $ time ./mmultTest +RTS -K100M > /dev/null real 0m10.962s user 0m10.790s sys 0m0.161s 这是一款使用4核(在4核MacBook Air上运行)的机型: 有人对这里发生的事有什么直觉吗?对于-N2和-N3,我的性能也比顺序性能慢;每个核
repa-algorithms-3.2.1.1
中的mmultP
函数(为了简洁起见,这里有一点压缩):
以下是线程运行时中的顺序运行:
$ time ./mmultTest +RTS -K100M > /dev/null
real 0m10.962s
user 0m10.790s
sys 0m0.161s
这是一款使用4核(在4核MacBook Air上运行)的机型:
有人对这里发生的事有什么直觉吗?对于-N2
和-N3
,我的性能也比顺序性能慢;每个核心似乎都增加了一些额外的时间
请注意,我确实观察到一些手工编写的Repa矩阵乘法代码的并行性带来了一些小的好处
更新:
令人费解;我将main
替换为
mmultBench :: IO ()
mmultBench = do
results <- mmultP arr brr
let reduced = sumAllS results
print reduced
带有运行时选项-N1-K100M
的标准基准测试产生:
mean: 1.361450 s, lb 1.360514 s, ub 1.362915 s, ci 0.950
std dev: 5.914850 ms, lb 3.870615 ms, ub 9.183472 ms, ci 0.950
而-N4-K100M
给了我:
mean: 556.8201 ms, lb 547.5370 ms, ub 573.5012 ms, ci 0.950
std dev: 61.82764 ms, lb 40.15479 ms, ub 102.5329 ms, ci 0.950
这是一个可爱的加速。我几乎会认为前面的行为是由于将生成的1000x1000数组写入stdout,但正如我所提到的,如果我交换自己的矩阵乘法代码,我确实观察到并行性的提高。我仍在挠头。这似乎很奇怪,但也许你只是在为并行性支付通常的费用,而没有获得好处--这类似于与荒谬的不平衡负载并联 看来肯定是出了什么问题。然而,让我震惊的是——这可能会部分解释您的结果——您只使用了一个
repa
combinator,mmultP
。框架几乎没有机会!如果我用zipWith
,foldAllP
等的字眼使事情复杂化——例如
1) 将矩阵打印到标准输出将使程序IO绑定。在这种情况下记录的任何加速数据都是谎言
2) 没有4核MacBook Air。它们都是2个核心,每个核心有2个超线程。一次只能运行两个线程。>-N2的任何加速都将是由于延迟隐藏造成的——核心上的第二个超线程可以运行,而第一个超线程在缓存未命中时暂停。使用3个核心时会得到什么?同样比sequential慢,但比
-N4
快。对于-N2
,情况也一样。是的,我也从你的代码中得到了很好的加速。在更新这个问题时,我几乎愚弄了自己,因为我用sumAllP
等做了一些并行的缩减,很好地改善了我在-N4
下的时间;似乎我真的没有在mmultP
上获得预期的利用率。使用我的示例中的simplemain=mmultP arr brr>>=print
是否会得到类似的时间?是的,我的结果与原始模块的结果类似。但我制作的main越复杂,我的结果就越好,至少就并行化而言。谢谢,这是我的怀疑。在手动滚动代码中进行交换导致总体性能低于mmultP
,但在-N2
和-N4
下,交换速度确实比w/-N1
稍快。这就是我困惑的根源。
mmultBench :: IO ()
mmultBench = do
results <- mmultP arr brr
let reduced = sumAllS results
print reduced
(arr, brr) = head &&& last $ map (fromListUnboxed (Z :. 1000 :. 1000 :: DIM2)) (replicate 2 [1..1000000])
mean: 1.361450 s, lb 1.360514 s, ub 1.362915 s, ci 0.950
std dev: 5.914850 ms, lb 3.870615 ms, ub 9.183472 ms, ci 0.950
mean: 556.8201 ms, lb 547.5370 ms, ub 573.5012 ms, ci 0.950
std dev: 61.82764 ms, lb 40.15479 ms, ub 102.5329 ms, ci 0.950
main :: IO ()
main = arr `xxx` brr >>= foldAllP (+) 0 >>= print where
xxx arr brr = R.zipWith (+) <$> complicated arr <*> complicated brr
complicated = mmultP brr >=> mmultP arr >=> mmultP brr >=> mmultP arr
$ time ./mmmult +RTS -K200M -N2
6.2713897715510016e16
real 0m8.742s
user 0m16.176s
sys 0m0.444s
$ time ./mmmult +RTS -K200M
6.2713897715512584e16
real 0m15.214s
user 0m14.970s
sys 0m0.239s