Haskell 在哈斯克尔有类似的发现吗?

Haskell 在哈斯克尔有类似的发现吗?,haskell,parallel-processing,Haskell,Parallel Processing,我有一些蛮力问题,我想在哈斯克尔解决。我的机器有16个内核,所以我想把我当前的算法加快一点 我有一个方法“tryCombination”,它返回Just(字符串)或Nothing。我的循环如下所示: findSolution = find (isJust) [tryCombination a1 a2 a3 n z p | a1 <- [600..700], a2 &

我有一些蛮力问题,我想在哈斯克尔解决。我的机器有16个内核,所以我想把我当前的算法加快一点

我有一个方法“tryCombination”,它返回Just(字符串)或Nothing。我的循环如下所示:

findSolution = find (isJust)  [tryCombination a1 a2 a3 n z p |
                               a1 <- [600..700],
                               a2 <- [600..700],
                               a3 <- [600..700],
                               n  <- [1..100],
                               ....
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
正如我已经提到的(见我的评论),所有的内核只工作了3秒钟(wenn所有的火花都被处理)。接下来的30秒所有的工作都是由一个核心完成的。我怎样才能进一步优化

更多编辑:

现在,我尝试了“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相比,这是一个很大的改进。第二个结论是,缓冲区大小应尽可能小,但应大于核心数。
但最好的是,我再也没有溢出或熄灭火花了。所有已成功转换。

根据
tryCombination
的懒散性和所需的并行化,其中一个可能会执行您想要的操作:

import Control.Parallel.Strategies
findSolution =
    find (isJust) $
    withStrategy (parList rseq) $
    [ tryCombination a1 a2 a3 n z p
    | a1 <- [600..700]
    , a2 <- [600..700]
    , a3 <- [600..700]
    , n  <- [1..100]]

我想应该看看
unab
包。
unabs
函数看起来很有前途。听起来很有趣,但我无法想象在这种特殊情况下如何应用unabs。你手边有一个片段吗?没有。从来没用过,看起来不错。我对这两个版本进行了一些测试,发现运行时之间没有差异。使用四个线程(-N4)只需要程序时间的一半,使用四个以上的线程不会进一步显著降低运行时间。在监视taks窗口时,我可以看到,在开始时,该程序完全消耗了16个内核中的4个。虽然我没有IO操作,但是cpu使用率下降到了5%。奇怪。。。。似乎我必须安装threadscope来进一步分析……如果
rdeepseq
rseq
没有区别,那么
tryCombination
很可能在确定某个问题是否为解决方案时,该解决方案随时可用。我大幅减少了组合参数集(仅需在大约一分钟内获得结果),因此不可能有任何解决方案。因此,我清楚地了解了它如何使用所有的内核。但现在我使用threadscope并计算出,产生了19000个火花,但只处理了8000个火花。这就是为什么仅在4秒钟内使用所有内核,然后仅主内核对剩余的9000个火花有效的原因。似乎是这样的这种并行化仍然有一些优化潜力。
findSolution =
    find (isJust) $
    withStrategy (parList rdeepseq) $
    [ tryCombination a1 a2 a3 n z p
    | a1 <- [600..700]
    , a2 <- [600..700]
    , a3 <- [600..700]
    , n  <- [1..100]]