7

重複の可能性:
F# は他の言語よりも遅いようです... 高速化するにはどうすればよいですか?

パターン マッチのパフォーマンスに少し興味があるので、次のテストを行いました。

poolEven0、1、2、3 の 10000 個の要素を含む (2500 個が等しい)

testSize = 100000

IfelseEven(100000) 650ミリ秒かかります(スイッチの方が高速ですが、コードを添付しませんでした)が、MatchEven(100000)10倍の時間である7000ミリ秒かかります

パフォーマンスの低下の原因はArray.Fold? IEnumerable.Aggregate速度が大幅に低下することは 100% 確信しています。しかし、F#は C# よりもうまく処理できると思いArray.FoldIEnumerable.Aggregateました。2 つの言語で最も一般的な (同等の) コーディング方法のパフォーマンスを比較したいが、それらを同一にする厳密な方法は比較したくない。

テストは x64 リリースで行われ、適切なウォームアップで平均 10 回以上の試行が行われます

C#:

public void IfelseEven(int testSize)
{
    Ifelse(testSize, poolEven);
}

void Ifelse(int testSize, int[] pool)
{
    long sum = 0;
    for (int i = 0; i < testSize; i++)
    {
        for (int j = 0; j < poolCapacity;j++ )
        {
            var item = pool[j];
            if (item == 0)
            {
                sum += 5;
            }
            else if (item == 1)
            {
                sum += 1;
            }
            else if (item == 2)
            {
                sum += 2;
            }
            else if (item == 3)
            {
                sum += 3;
            }
            else
            {
                sum += 4;
            }
        }
    }
}

public void MatchEven(int testSize)
{
    PatternMatch.myMatch(testSize, poolEven);
}

F#:

module PatternMatch

let mat acc elem =
    acc +
    match elem with
    | 0 -> 5L
    | 1 -> 1L
    | 2 -> 2L
    | 3 -> 3L
    | _ -> 4L

let sum (pool:int[])=
    Array.fold mat 0L pool;

let myMatch testSize pool=
    let mutable tmp = 0L
    for i=0 to testSize do
        tmp <- sum(pool) + tmp
    tmp
4

2 に答える 2

11

締めくくりに投票します。このゲームは一日中プレイできます。コードによって実行時間が異なる理由の詳細については、この質問と回答を参照してください。F# 関数を高速化したい場合は、次を試してください。

let ifElse testSize (pool: _[]) = 
  let mutable sum = 0L
  for i = 0 to testSize - 1 do
    for j = 0 to pool.Length - 1 do
      match pool.[j] with
      | 0 -> sum <- sum + 5L
      | 1 -> sum <- sum + 1L
      | 2 -> sum <- sum + 2L
      | 3 -> sum <- sum + 3L
      | _ -> sum <- sum + 4L
  sum

私の測定では、これはC#関数を簡単に舐めます(さらに短く、読みやすくなっています):

C# 5655
F# 4003

ちなみに、レピーはコメントでそれを釘付けにしました。私はあなたのコードをプロファイリングし、時間の 78% が費やされましArray.foldた — タイトなループでは良くありません.

于 2012-08-29T18:53:52.170 に答える
7

matchコメントで述べたように、まったく異なるパターンを使用することで、 vsif/elseifを単独で比較することはできません。ループとフォールドと再帰の比較は、まったく別の問題です。

より直接的な比較 (ループ、ダニエルの応答と同じ) を使用すると、以下の結果が得られました。リリース ビルド、.NET 4.5、x64 ターゲット アーチ。

  • C# と F#if\elseifのアプローチはほぼ同じように実行されます (この不自然な例では)。

  • F#はどちらの言語matchよりも一貫して高速でした(この不自然な例では)if\elseif

  • C#switchは一貫して最速でした (この不自然な例では)。

于 2012-08-29T18:58:39.933 に答える