dlaczego Seq.iter jest 2x szybszy niż dla pętli, jeśli cel jest dla x64?

Zastrzeżenie: To jest mikro-benchmark, proszę nie komentować cytatów, takich jak „przedwczesna optymalizacja jest zła”, jeśli czujesz się niezadowolony z tematu.

Przykłady to wydanie przeznaczone dla x64, .Net4.5 Visual Studio 2012 F # 3.0 i uruchamiane w systemie Windows 7 x64

Po profilowaniu zawęziłem wąskie gardło jednej z moich aplikacji, więc chcę poruszyć to pytanie:

Obserwacja

Jeśli w środku nie ma pętlifor in pętla lubSeq.iter, wtedy jest jasne, że oba mają podobną prędkość. (update2 vs update4)

Jeśli w środku jest pętlafor in pętla lubSeq.iter, wydaje sięSeq.iter jest 2x szybszy niżfor in. (aktualizacja a aktualizacja3) dziwne? (jeśli uruchomione w fsi byłyby podobne)

Jeśli jest przeznaczony dla anycpu i działa w x64, nie ma różnicy w czasie. Więc pytanie brzmi:Seq.iter (update3) zwiększyłoby 2x prędkość, jeśli celem jest x64

Zajęty czas:
update:   00:00:11.4250483 // 2x as much as update3, why?
updatae2: 00:00:01.4447233
updatae3: 00:00:06.0863791
updatae4: 00:00:01.4939535
Kod źródłowy:
open System.Diagnostics
open System

[<EntryPoint>]
let main argv = 
    let pool = seq {1 .. 1000000}

    let ret = Array.zeroCreate 100

    let update pool =
        for x in pool do
            for y in 1 .. 200 do
                ret.[2] <- x + y

    let update2 pool =
        for x in pool do
            //for y in 1 .. 100 do
                ret.[2] <- x


    let update3 pool =
        pool
            |> Seq.iter (fun x ->
                                  for y in 1 .. 200 do
                                      ret.[2] <- x + y)

    let update4 pool =
        pool
            |> Seq.iter (fun x ->
                                  //for y in 1 .. 100 do
                                      ret.[2] <- x)


    let test n =
        let run = match n with
                  | 1 -> update
                  | 2 -> update2
                  | 3 -> update3
                  | 4 -> update4
        for i in 1 .. 50 do
            run pool

    let sw = new Stopwatch()
    sw.Start()
    test(1)
    sw.Stop()
    Console.WriteLine(sw.Elapsed);

    sw.Restart()
    test(2)
    sw.Stop()
    Console.WriteLine(sw.Elapsed)

    sw.Restart()
    test(3)
    sw.Stop()
    Console.WriteLine(sw.Elapsed)

    sw.Restart()
    test(4)
    sw.Stop()
    Console.WriteLine(sw.Elapsed)
    0 // return an integer exit code

questionAnswers(2)

yourAnswerToTheQuestion