F#:告诉我我对使用 Async.Parallel 的遗漏

标签 f# parallel-processing

好的,所以我正在做 ProjectEuler 问题 #14,我正在摆弄优化以感受 f#。

在以下代码中:

let evenrule n = n / 2L
let oddrule n = 3L * n + 1L

let applyRule n =
    if n % 2L = 0L then evenrule n
    else oddrule n

let runRules n =
    let rec loop a final =
        if a = 1L then final
        else loop (applyRule a) (final + 1L)
    n, loop (int64 n) 1L


let testlist = seq {for i in 3 .. 2 .. 1000000 do yield i } 

let getAns sq = sq |> Seq.head

let seqfil (a,acc) (b,curr) = if acc = curr then (a,acc) else if acc < curr then (b,curr) else (a,acc)

let pmap f l = 
    seq { for a in l do yield async {return f a} }
    |> Seq.map Async.RunSynchronously

let pmap2 f l = 
    seq { for a in l do yield async {return f a} }
    |> Async.Parallel
    |> Async.RunSynchronously

let procseq f l = l
                  |> f runRules
                  |> Seq.reduce seqfil
                  |> fst

let timer = System.Diagnostics.Stopwatch()
timer.Start()
let ans1 = testlist |> procseq Seq.map // 837799    00:00:08.6251990
printfn "%A\t%A" ans1 timer.Elapsed
timer.Reset()

timer.Start()
let ans2 = testlist |> procseq pmap
printfn "%A\t%A" ans2 timer.Elapsed // 837799   00:00:12.3010250
timer.Reset()

timer.Start()
let ans3 = testlist |> procseq pmap2
printfn "%A\t%A" ans3 timer.Elapsed // 837799   00:00:58.2413990
timer.Reset()

为什么 Async.Parallel 代码与直接映射相比运行速度非常慢?我知道我不应该看到那么大的影响,因为我只使用双核 mac。

请注意,我不需要帮助解决问题 #14,我只想知道我的并行代码是怎么回事。

最佳答案

Async.Parallel的使用似乎是正确的。这些数字看起来确实很可疑,但我没有立即看出这里可能有什么问题。

无论如何,异步工作流确实更适合涉及一些异步操作(例如 I/O、通信、等待事件等)的计算。对于 CPU 密集型任务,最好使用 .NET 并行扩展(现在是 .NET 4.0 的一部分;不幸的是,没有 .NET 2.0 版本)。

要从 F# 执行此操作,您需要 F# PowerPackFSharp.PowerPack.Parallel.Seq.dll汇编,其中包含用于处理序列的高阶函数的并行版本(例如 map :-))

这些函数返回 pseq<'a> 类型的值(在 C# 中称为 ParallelQuery<T>),表示并行运行的延迟计算(当您在管道中使用多个操作时,这可以实现更好的优化)。还有PSeq.reduce函数,所以你可能也想在你的处理中使用它(除了 PSeq.map )。

关于F#:告诉我我对使用 Async.Parallel 的遗漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2678850/

相关文章:

python - 如何使用 joblib Python 返回矩阵?

c - 为什么并行和串行版本的执行时间几乎相同

f# - 在 F# 中使用另一种记录类型扩展记录类型

F# 如何标记用户输入 : separating numbers, 单位、单词?

asp.net-mvc - FSharp.Core.sigdata 未与 FSharp.Core 一起找到

multithreading - 什么是 "Linearizability"?

r - R 雪中的 makeCluster 函数无限期挂起

c# - 如何增加 Parallel.For 中特定值的索引?

html - 如何在 Fulma/Fable 中插入自定义 HTML 标签?

ado.net - 在 f# 匹配语句中,如何匹配字节 [] 类型?