Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#:告诉我我';我不知道如何使用Async.Parallel_F#_Parallel Processing - Fatal编程技术网

F#:告诉我我';我不知道如何使用Async.Parallel

F#:告诉我我';我不知道如何使用Async.Parallel,f#,parallel-processing,F#,Parallel Processing,好的,所以我在做ProjectEuler问题14,我在摆弄优化,以便感觉f#out 在以下代码中: 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

好的,所以我在做ProjectEuler问题14,我在摆弄优化,以便感觉f#out

在以下代码中:

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()
n=n/2L
设规则n=3L*n+1L
让我们一起来=
如果n%2L=0L,则规则n
其他规则
让我们运行规则n=
让rec循环一个决赛=
如果a=1L,则为最终值
else循环(应用规则a)(最终+1L)
n、 环路(int64 n)1L
让testlist=seq{3..2..1000000中的i产生i}
让getAns sq=sq |>Seq.head
假设seqfil(a,acc)(b,curr)=如果acc=curr,那么(a,acc)else如果accSeq.map Async.RunSynchronously
设pmap2f l=
seq{for a in l do产生异步{返回fa}
|>异步并行
|>异步运行
设procseq f l=l
|>f运行规则
|>Seq.减少seqfil
|>fst
让定时器=System.Diagnostics.Stopwatch()
timer.Start()
设ans1=testlist |>procseq Seq.map//837799 00:00:08.6251990
printfn“%A\t%A”ans1计时器。已过
timer.Reset()
timer.Start()
设ans2=testlist |>procseq pmap
printfn“%A\t%A”ans2计时器。运行时间//837799 00:00:12.3010250
timer.Reset()
timer.Start()
设ans3=testlist |>procseq pmap2
printfn“%A\t%A”ans3计时器。运行时间//837799 00:00:58.2413990
timer.Reset()
为什么Async.Parallel代码与直接映射相比运行得非常慢?我知道我不应该看到这么大的影响,因为我只使用双核mac


请注意,我不需要帮助解决问题,我只想知道我的并行代码出了什么问题。

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

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

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


这些函数在我的框中返回类型为
pseq的值,运行非异步函数大约需要半秒钟。因为这里有大约50万个工作项,这意味着每个工作项平均运行时间约为1微秒

这些项目太小,无法单独尝试并行化。执行线程调度和同步的开销将主导实际工作。您需要选择更好的粒度

(我将编写一些快速代码…)

编辑:

好的,代码原样不太容易在不进行重大重写的情况下更改批处理粒度,因此我没有新的代码可以共享,不会泄露太多信息。但是,我能够使它在我的2芯盒上运行的速度提高近一倍,方法是每批生成50000个元素,并在每批上执行“map reduce”,在大约10批上执行“parallel map reduce”

另见

特别是“任务粒度”部分

我只是想知道我的并行代码出了什么问题

嘿,你的并行代码没有什么问题。;-)

以下是我解决问题的方法:

  let rec inside (a : _ array) n =
    if n <= 1L || a.[int n] > 0s then a.[int n] else
      let p =
        if n &&& 1L = 0L then inside a (n >>> 1) else
          let n = 3L*n + 1L
          if n < int64 a.Length then inside a n else outside a n
      a.[int n] <- 1s + p
      1s + p
  and outside (a : _ array) n =
    let n = if n &&& 1L = 0L then n >>> 1 else 3L*n + 1L
    1s + if n < int64 a.Length then inside a n else outside a n

  let euler14 n =
    let a = Array.create (n+1) 0s
    let a = Array.Parallel.init (n+1) (fun n -> inside a (int64 n))
    let i = Array.findIndex (Array.reduce max a |> (=)) a
    i, a.[i]
让rec进入(a:uu数组)n=
如果为n0s,则为[int n]else
让p=
如果n&&1L=0L,则在a(n>>>1)内,否则
设n=3L*n+1L
如果n>1个其他3L*n+1L
1s+如果na内部(int64n))
设i=Array.findIndex(Array.reduce max a |>(=)a
i、 a[我]

该程序在安全竞争条件下使用推测并行,并在我的8个内核上实现适度的2倍加速。

为什么并行执行,然后同步执行?你的管道看起来很奇怪,因为我不知道如何获取数值?我的印象是Async.Parallel给了你一个列表,设置为并行处理,然后Async.runsynchronous运行Async.Parallel-ized序列并等待它完成(但它是并行处理的)诅咒!这限制了在我的电脑上进行并行扩展的实验。快点,mono!让我们升级到4.0!看起来Mono的人肯定对并行扩展感兴趣,但我不确定目前的状况。。。不久前,我自己编写了一个
PSeq.map
PSeq.filter
的实现(),但是性能可能不是最好的…有一个.NET2.0的并行扩展版本。它作为被动扩展的一部分发布。这篇文章帮助我更开阔了眼界。我鼓励其他人也阅读它!