非常に単純なC#とF#テストプログラムを作成しました。 #71、MS のF#1797ミリなぜLINQ(c#)とSeq(f#)のパフォーマンスの違いがありますか
C
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static int Remainder(int num)
{
return num % 2;
}
static int SumOfremainders(IEnumerable<int> list)
{
var sum = 0;
foreach (var num in list)
{
sum += Remainder(num);
}
return sum;
}
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
var nums = Enumerable.Range(1, 10000000);
sw.Start();
var a = SumOfremainders(nums);
sw.Stop();
Console.WriteLine("Duration " + (sw.ElapsedMilliseconds));
Console.WriteLine("Sum of remainders: {0}", a);
}
}
}
let remainder x = x % 2
let sumORemainders n =
n
|> Seq.map(fun n-> remainder n)
|> Seq.sum
let seqb = Seq.init 10000000(fun n->n)
let timer =System.Diagnostics.Stopwatch()
timer.Start()
let a =(sumORemainders seqb)
timer.Stop()
printfn "Elapsed Time: "
System.Console.WriteLine timer.ElapsedMilliseconds
printfn "Sum of squares of 1-100: %d" a
[<EntryPoint>]
let main argv =
0 // return an integer exit code
を私は#
let remainder x = x % 2
let sumORemainders (input:seq<int>) =
let mutable sum = 0
let en = input.GetEnumerator()
while (en.MoveNext()) do
sum <- sum + remainder en.Current
sum
let seqb = Seq.init 10000000(fun n->n)
let timer =System.Diagnostics.Stopwatch()
timer.Start()
let a =(sumORemainders seqb)
timer.Stop()
printfn "Elapsed Time: "
System.Console.WriteLine timer.ElapsedMilliseconds
printfn "Sum of squares of 1-100: %d" a
[<EntryPoint>]
let main argv =
0 // return an integer exit code
cより同様の動作F位から第二のバージョンを作ったが、結果は、有意に(1650ms)に変更しないではありません私は2つの言語間の速度の大きな違いを理解していません。
2つのプログラムは非常に似たILコードを持ち、どちらもIEnumerableを使用します。さらに、F#は関数呼び出しを操作に置き換えます。
私はf#ILコードに基づいてc#コードを書き換えました。
static int SumOfremainders(IEnumerable<int> list)
{
var sum = 0;
IEnumerator<int> e = list.GetEnumerator();
while (e.MoveNext())
{
sum += e.Current % 2;
}
return sum;
}
2つのプログラムのILコードは同じですが、速度はまだ非常に異なります。 私はフォギーファインダー
遅いコード
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[Serializable]
internal class [email protected] : FSharpFunc<int, int>
{
internal [email protected]()
{
}
public override int Invoke(int n)
{
return n;
}
}
[CompilationMapping(SourceConstructFlags.Value)]
public static IEnumerable<int> seqb
{
get
{
return [email protected];
}
}
速いコード
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[CompilationMapping(SourceConstructFlags.Value)]
public static int[] seqb
{
get
{
return [email protected];
}
}
私は質問が重複していることに同意しません。もう1つの質問は開いていますが、これははるかに具体的です。しかし、私はOPが 'Seq/LINQ'を含むように質問を言い換えるべきだと思う(LINQは遅いSeqは遅い) – FuleSnabel
これはあなたのC#コードとF#が実際に異なっているからです。 –
これは: 'let seqb = Seq.init 10000000(fun n-> n)'は 'var nums = Enumerable.Range(1、10000000);と等しくないので、 –