【发布时间】:2015-04-23 05:19:53
【问题描述】:
我有一些我喜欢在 Haskell 中解决的蛮力问题。我的机器有 16 个核心,所以我想稍微加快一下我目前的算法。
我有一个方法“tryCombination”,它返回 Just (String) 或 Nothing。我的循环如下所示:
findSolution = find (isJust) [tryCombination a1 a2 a3 n z p |
a1 <- [600..700],
a2 <- [600..700],
a3 <- [600..700],
n <- [1..100],
....
我知道有一个特殊的 parMap 可以并行化 map 函数。如果线程真的找到了第一次出现,那么 mapFind 可能会很棘手,因为它是不可预测的。但是有没有类似 mapAny 的东西来加快搜索速度?
编辑:
我使用“withStrategy (parList rseq)”sn-p 重写了代码。状态报告如下所示:
38,929,334,968 bytes allocated in the heap
2,215,280,048 bytes copied during GC
3,505,624 bytes maximum residency (795 sample(s))
202,696 bytes maximum slop
15 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 44922 colls, 44922 par 37.33s 8.34s 0.0002s 0.0470s
Gen 1 795 colls, 794 par 7.58s 1.43s 0.0018s 0.0466s
Parallel GC work balance: 4.36% (serial 0%, perfect 100%)
TASKS: 10 (1 bound, 9 peak workers (9 total), using -N8)
SPARKS: 17576 (8198 converted, 9378 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.00s ( 0.00s elapsed)
MUT time 81.79s ( 36.37s elapsed)
GC time 44.91s ( 9.77s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 126.72s ( 46.14s elapsed)
Alloc rate 475,959,220 bytes per MUT second
Productivity 64.6% of total user, 177.3% of total elapsed
gc_alloc_block_sync: 834851
whitehole_spin: 0
gen[0].sync: 10
gen[1].sync: 3724
正如我已经提到的(请参阅我的 cmets),所有核心仅工作三秒钟(所有火花都已处理)。 30s以下的所有工作都是由单核完成的。我怎样才能进一步优化?
更多编辑:
我现在尝试了“withStrategy (parBuffer 10 rdeepseq)”,并调整了不同的缓冲区大小:
Buffersize GC work Balance MUT GC
10 50% 11,69s 0,94s
100 47% 12,31s 1,67s
500 40% 11,5 s 1,35s
5000 21% 11,47s 2,25s
首先我可以说,与没有任何多线程的 59 相比,这是一个很大的改进。第二个结论是,缓冲区大小应尽可能小但大于内核数。 但最好的是,我不再溢出或熄灭火花。全部转换成功。
【问题讨论】:
-
我会猜看的地方是
unamb包。unambs函数看起来很有希望。 -
听起来很有趣,但我无法想象在这种特殊情况下如何应用 unamb。你手头有sn-p吗?
-
不。从来没用过。
标签: haskell parallel-processing