I'm comparing performance of this F# function:
let e28 N =
seq {for i in 2L..2L..N do for j in 1..4 -> i} |> Seq.scan (+) 1L |> Seq.sum
with Python 3.3 equivalents:
def e28a(N = 100000):
diagNumber = 1
sum = diagNumber
for width in range(2, N+1, 2):
for j in range(4):
diagNumber += width
sum += diagNumber
return sum
import itertools as it
def e28b(N = 100000):
return sum(it.accumulate(it.chain([1], (i for i in range(2, N+1, 2) for j in range(4)))))
import numpy as np
def e28c(N = 100000):
return np.sum(np.cumsum(np.fromiter(chain([1], (i for i in range(2, N+1, 2) for j in range(4))), np.int64)))
and I'm getting 64-bit CPython 3.3.1 performance on Windows 7 about 574 times slower than C++. Here are the times for N = 100000:
e28: 23ms; e28a: 48.4ms; e28b: 49.7ms; e28c: 40.2ms; C++ version: 0.07ms
Is there a low hanging fruit in optimizing Python code without altering the underlying algorithm?
The F# version can be sped up by ~10x by switching to a procedural, mutable approach (like your python e28a
). When the "payload operation" (in this case, just +) is so trivial, the use of combinators ends up adding a relatively significant overhead. As a side note, Seq.sum
uses checked arithmetic, which also adds a touch of overhead.
One of the nice things about F# is that you can fall back to procedural/mutable style if needed for a perf-critical hot path.
let e28_original N =
seq {
for i in 2UL..2UL..N do
for j in 1..4 do
yield i
}
|> Seq.scan (+) 1UL
|> Seq.sum
let e28_mutable N =
let mutable sum = 1UL
let mutable total = sum
for i in 2UL..2UL..N do
for j in 1..4 do
sum <- sum + i
total <- total + sum
total
let time f =
f () |> ignore // allow for warmup / JIT
let sw = System.Diagnostics.Stopwatch.StartNew()
let result = f ()
sw.Stop()
printfn "Result: %A Elapsed: %A" result sw.Elapsed
time (fun _ -> e28_original 100000UL)
time (fun _ -> e28_mutable 100000UL)
Result
Result: 666691667100001UL Elapsed: 00:00:00.0429414
Result: 666691667100001UL Elapsed: 00:00:00.0034971
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With