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
“的影响是什么?”;如果为false,则为();在计算机语言基准游戏';s F#螺纹圈入口?_F# - Fatal编程技术网

“的影响是什么?”;如果为false,则为();在计算机语言基准游戏';s F#螺纹圈入口?

“的影响是什么?”;如果为false,则为();在计算机语言基准游戏';s F#螺纹圈入口?,f#,F#,计算机语言基准测试游戏包含一行看似无用的代码:如果为false,那么()。当我注释掉这一行时,程序运行速度要快得多(对于50000000的输入,~2s对~55s),并产生相同的结果。这是怎么回事?为什么这条线在那里?编译器究竟是如何处理看似不可操作的对象的 守则: let ringLength = 503 let cells = Array.zeroCreate ringLength let threads = Array.zeroCreate ringLength let answer =

计算机语言基准测试游戏包含一行看似无用的代码:
如果为false,那么()
。当我注释掉这一行时,程序运行速度要快得多(对于50000000的输入,~2s对~55s),并产生相同的结果。这是怎么回事?为什么这条线在那里?编译器究竟是如何处理看似不可操作的对象的

守则:

let ringLength = 503

let cells = Array.zeroCreate ringLength
let threads = Array.zeroCreate ringLength
let answer = ref -1

let createWorker i = 
    let next = (i+1)%ringLength
    async { let value = cells.[i]
            if false then () 
            match value with
            | 0 -> answer := i+1
            | _ -> 
                cells.[next] <- value - 1 
                return! threads.[next] }

[<EntryPoint>]
let main args = 
    cells.[0] <- if args.Length>0 then int args.[0] else 50000000
    for i in 0..ringLength-1 do 
        threads.[i]<-createWorker i

    let result = Async.StartImmediate(threads.[0])
    printfn "%d" !answer
    0
let ringLength=503
让单元格=Array.zeroCreate ringLength
让threads=Array.zeroCreate ringLength
让答案=ref-1
让createWorker i=
设next=(i+1)%ringLength
异步{let value=单元格。[i]
如果为false,则()
匹配值
|0->答案:=i+1
| _ -> 

单元格。[下一步]如果计算表达式包含
If false then()
,则异步工作流的转换方式略有不同。在该行中,它使用
async.Combine
。稍微简化的代码如下所示:

async.Delay(fun () ->
  value = cells.[i]
  async.Combine
    ( async.Return(if false then ())
      async.Delay(fun () ->
        match value with (...) ) ))
转换插入了
Combine
,因为
if
循环完成的(可能)异步计算需要与以下代码组合。现在,如果删除
if
,您会得到如下结果:

async.Delay(fun () ->
  value = cells.[i]
  match value with (...) ) ))
不同之处在于,现在在传递给
Delay
的函数中立即完成了更多的工作

编辑:我认为这造成了差异,因为代码使用了
Async.startimimediate
而不是
Async.Start
,但情况似乎并非如此。事实上,我根本不明白为什么代码使用异步工作流


编辑II.:我不完全确定Mono,但它肯定会在F#interactive中复制-在那里,带有
组合的版本大约慢4倍(这是我所期望的,因为函数分配开销).

我最初编写了这段代码。我不记得添加这一行的确切原因,但我猜,如果没有它,优化器会做一些我认为不符合基准游戏精神的事情。首先使用异步的原因是为了将尾部调用延续到下一个异步(这就是为什么它的性能比C#mono好得多的原因)。
-Jomo

+1是一个权威的答案(比如它),但我很好奇为什么你会故意惩罚基准测试的性能……回想起来,我相信我想炫耀异步,它是不同的合法执行上下文,同时仍然在同一硬件线程上共享延续(采用与Go goroutines类似的使用模式)。如果没有这一行,F#会将整个过程有效地展开成一个while循环。这对于基准测试来说是很不错的,但一旦你尝试将代码用于实际的事情,性能就会下降20倍左右。