2016-01-10 8 views
5

Wersja (calc1) za pomocą bezpośredniej funkcji zewnętrznej zajmuje około 1 s.F #: dlaczego używanie wersji funkcji zewnętrznej jest szybsze niż funkcja przekazywania jako argument

Ale wersja (calc2) z funkcją przekazu jako parametrem funkcji zajmuje około 2s, czyli 2x wolniej. Czemu?

open System.Diagnostics 
open System.Numerics 

let width = 1920 
let height = 1200 
let xMin = -2.0 
let xMax = 1.0 
let yMin = -1.0 
let yMax = 1.0 
let scaleX x = float x * (xMax - xMin)/float width + xMin 
let scaleY y = float y * (yMax - yMin)/float height - yMax 

let fn (z:Complex) (c:Complex) = z * z + c 

let calc1 width height = 
    let iterFn z c = 
     let rec iterFn' (z:Complex) c n = 
      if z.Magnitude > 2.0 || n >= 255 then n 
      else iterFn' (fn z c) c (n + 1) 
     iterFn' z c 0 

    Array.Parallel.init (width * height) (fun i -> 
     let x, y = i % width, i/width 
     let z, c = Complex.Zero, Complex(scaleX x, scaleY y) 
     (x, y, iterFn z c) 
    ) 

let calc2 width height fn = 
    let iterFn z c = 
     let rec iterFn' (z:Complex) c n = 
      if z.Magnitude > 2.0 || n >= 255 then n 
      else iterFn' (fn z c) c (n + 1) 
     iterFn' z c 0 

    Array.Parallel.init (width * height) (fun i -> 
     let x, y = i % width, i/width 
     let z, c = Complex.Zero, Complex(scaleX x, scaleY y) 
     (x, y, iterFn z c) 
    ) 

Execute w F # interaktywne uzyskać następujące wyniki:

> calc1 width height |> ignore 
Real: 00:00:00.943, CPU: 00:00:03.046, GC gen0: 10, gen1: 8, gen2: 2 
val it : unit =() 

> calc2 width height fn |> ignore 
Real: 00:00:02.033, CPU: 00:00:07.484, GC gen0: 9, gen1: 8, gen2: 1 
val it : unit =() 

F # 4.0.1, NET 4.6.1

Odpowiedz

1

Podejrzewam, że w pierwszym przypadku, fn jest inlined.

Mijając go jako paramter zapobiega tej optymalizacji od występującego, więc jest wolniejszy

+0

Aby dodać do odpowiedzi Johna Palmera, można łatwo sprawdzić hipotezę poprzez dodanie 'inline' modyfikator' definicji fn' użytkownika. Jeśli to był problem, spowolnienie powinno zniknąć. – piaste

+0

@piaste Ustawienie 'fn' w linii nie wpływa na wydajność. Ale wzrost wydajności, jeśli 'calc2' również wbudowane. – anpv

+0

@piaste - to nie działa inline. –

Powiązane problemy