[英]F# vs C# performance for prime number generator
我注意到F#和C#中看似相同的代碼不會執行相同的操作。 F#的數量級更慢。 作為一個例子,我提供的代碼生成素數/給出F#和C#中的第n個素數。 我的F#代碼是:
let rec isprime x =
primes
|> Seq.takeWhile (fun i -> i*i <= x)
|> Seq.forall (fun i -> x%i <> 0)
and primes =
seq {
yield 2
yield! (Seq.unfold (fun i -> Some(i, i+2)) 3)
|> Seq.filter isprime
}
let n = 1000
let start = System.DateTime.Now
printfn "%d" (primes |> Seq.nth n)
let duration = System.DateTime.Now - start
printfn "Elapsed Time: "
System.Console.WriteLine duration
而C#看起來像這樣:
class Program
{
static bool isprime(int n)
{
foreach (int p in primes())
{
if (p * p > n)
return true;
if (n % p == 0)
return false;
}
return true;
}
static IEnumerable<int> primes()
{
yield return 2;
for (int i=3; ; i+=2)
{
if (isprime(i))
yield return i;
}
}
static void Main(string[] args)
{
int n = 1000;
var pr = primes().GetEnumerator();
DateTime start = DateTime.Now;
for (int count=0; count<n; count++)
{
pr.MoveNext();
}
Console.WriteLine(pr.Current);
DateTime end = DateTime.Now;
Console.WriteLine("Duration " + (end - start));
}
}
當我測量不同的n
我獲得至少7x的C#優勢如下:
我的問題:
編輯1:我已經意識到算法本身可以通過僅遍歷isprime中的奇數和非素數來改進,使其成為非遞歸的,但這對於提出的問題是一種垂直的事實:)
這個:
這兩個程序是否相同?
這是一個哲學問題。
在我看來, isprime
的C#和F#實現的isprime
總是會同意任何給定的x
,所以在這個意義上它們是等價的。 但是,在你如何實現它們方面存在很多差異(例如, Seq.unfold
會創建一個中間的IEnumerable<_>
值,然后Seq.filter
將創建另一個,所以你生成了更多的短命對象並在F#代碼中使用了更多的函數調用,因此,就各個編譯器生成的低級指令而言,它們並不等同,這一點都不奇怪。
如果你願意,你可以創建與C#代碼更相似的F#代碼,代價是更加迫切和不那么慣用:
let rec primes =
seq {
yield 2
let mutable x = 3
while true do
if isprime x then
yield x
x <- x + 2
}
and isprime x =
use e = primes.GetEnumerator()
let rec loop() =
if e.MoveNext() then
let p = e.Current
if p * p > x then true
elif x % p = 0 then false
else loop()
else true
loop()
primes |> Seq.item 5000
使用此實現在我的機器上大約需要0.6秒,相比之下,您的實現大約需要2.7秒。 我認為一般來說,F# seq
表達式的代碼生成通常比C#迭代器的代碼生成稍差,所以如果C#仍然運行得更快,我也不會感到驚訝。 (但是請注意,有些成語在F#中比在C#中更快,所以F#並不總是更慢 - 根據我的經驗,這兩種語言總體上相當,我發現編寫F#代碼更加愉快)。
在任何情況下,我不建議如何使F#編譯器的輸出更接近C#編譯器的細節,而是建議尋找算法改進。 例如,簡單地在原始定義primes
的末尾調用Seq.cache
會使primes |> Seq.item 5000
在我的機器上只需0.062秒,這比原始C#快得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.