c# - 高速 - vb net parallel for 使い方




.NETではループが速く実行される 'for'または 'foreach'ですか? (20)

2つはほぼ同じように動作します。 両方を使用するコードを書いてから、彼にILを示してください。 同等の計算を示すはずです。つまり、パフォーマンスに差はありません。

C#/ VB.NET / .NETでは、どのループが速く実行さforか、 foreach for実行されますか?

これまでのforループは、 foreachループよりも速く動作しています。以前は、すべてのコレクション、ジェネリックコレクション、すべての配列などに当てはまりました。

私はGoogleを精査し、いくつかの記事を見つけましたが、そのほとんどは決定的ではありません(記事へのコメントを読む)。

理想的なのは、各シナリオをリストし、同じシナリオに最適なソリューションを用意することです。

たとえば(どのようにするべきかの例)

  1. 1000+文字列の配列を反復するために - forforeachよりも優れています
  2. IList (非汎用)文字列を反復するために - foreach

いくつかの参考文献は、ウェブ上で同じものが見つかりました:

  1. Emmanuel Schanzerによるオリジナルの壮大な古い記事
  2. コードプロジェクトFOREACH対。 にとって
  3. ブログ - foreachまたはforeach 、それは質問です。
  4. ASP.NETフォーラム - NET 1.1 C# for foreach

[編集]

私はそれの読みやすさの面だけでなく、事実や数字に本当に興味があります。 パフォーマンス最適化の最後のマイルが圧迫されたアプリケーションがあります。



TechEd 2005のJeffrey Richter:

"私はC#コンパイラが基本的に私にはうそつきであることを何年にもわたって学びました。" .. "それは多くのことにある。 .. "あなたがforeachループをするときのように..." ... "それはあなたが書いたコードの小さな行ですが、C#コンパイラが驚くべきことを吐き出すものです。 try / finallyブロックでfinallyブロックの中で変数をIDisposableインターフェイスにキャストし、キャストが成功するとそのループのDisposeメソッドを呼び出します。ループ内でCurrentプロパティとMoveNextメソッドをループ内で繰り返し呼び出すと、オブジェクトはカバーの下に作成されています。多くの人がforeachを使用しています。なぜなら、非常に簡単なコーディングであるためです。 ".." foreachは、代わりにsquareを使用してコレクションを繰り返した場合、ブラケットの表記法は、単にインデックスを実行するだけで、はるかに高速で、ヒープ上にオブジェクトを作成することはありません... "

オンデマンドWebキャスト: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US : http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US


「forループが使えることを彼に納得させるために使うことができる議論はありますか?」

いいえ、あなたの上司が、プログラミング言語の構成要素をどのように使用するかを教えてくれるレベルまで微調整しているのであれば、本当にあなたが言うことはありません。 ごめんなさい。


foreachより速いかどうかは本当にポイントの外にあります。 私は真剣に1つを選択することは、あなたのパフォーマンスに大きな影響を与えることを疑う。

アプリケーションを最適化する最善の方法は、実際のコードをプロファイリングすることです。 これは、最も多くの仕事/時間を占める方法を特定します。 それらを最初に最適化してください。 それでもパフォーマンスが許容できない場合は、手順を繰り返します。

原則として、マイクロオプティマイゼーションから遠ざかることを推奨します。めったに大きな利益を得られないからです。 特定されたホット・パスを最適化する場合(つまり、プロファイリングがいくつかの高度に使用されている方法を識別している場合は、それらを広範囲に最適化することが理にかなっています)


foreachループをforループよりも優先させる理由は非常にあります。 foreachループを使用することができれば、あなたの上司はあなたがすべきことは正しいです。

しかし、すべての反復が、順番に1つずつ順番にリストを通過するわけではありません。 彼が禁じられているなら、間違っている。

私があなたであれば、あなたの自然なforループを再帰的に回すことです。 それは彼に教えてくれるだろうし、それはまたあなたのための良い精神運動でもある。


forループのようなものの使用を完全に禁止するのはちょっと変わったようです。

ここでは、2つのループ間の多くのパフォーマンスの違いをカバーする興味深い記事があります。

私は個人的に私はforeachをループのために少し読みやすくすると思いますが、forループがより適切であればforeachループをインクルードするために余分な長いコードを書く必要はありません。


あなたが特定の速度最適化プロセスに入っていない限り、私はコードを読んで維持するのが最も簡単な方法を使用すると言うでしょう。

コレクションクラスの1つのようにイテレータが既に設定されている場合、foreachは簡単なオプションです。 そして、それが整数化されていれば、iteratingしているので、forはおそらくもっときれいです。


これは、「より速い」ほとんどの質問と同じ2つの答えを持っています:

1)あなたが測定しない場合、あなたは知らない。

2)(ため...)それは依存します。

これは、 "this [int index]"メソッドがどれだけ高価であるかにかかわらず、反復処理されるIEnumerableの型(1つまたは複数)の "MoveNext()"メソッドがどれほど高価かによって異なります。

"foreach"キーワードは、一連の操作の略語です。IEnumerableでGetEnumerator()を1回呼び出し、繰り返しごとにMoveNext()を呼び出すなど、いくつかの型チェックを行います。 パフォーマンス測定に影響を与える可能性が最も高いのは、O(N)回呼び出されるためMoveNext()のコストです。 たぶんそれは安いですが、そうでないかもしれません。

"for"キーワードはより予測可能ですが、ほとんどの "for"ループの中には "collection [index]"のようなものがあります。 これは単純な配列のインデックス作成操作のように見えますが、実際はメソッド呼び出しです。そのコストは、反復処理しているコレクションの性質に完全に依存します。 おそらくそれは安いですが、そうでないかもしれません。

コレクションの基本構造が本質的にリンクリストである場合、MoveNextは安価ですが、インデクサーはO(N)コストを持つ可能性があり、forループの真のコストをO(N * N)にします。


これはあなたを救うはずです:

public IEnumerator<int> For(int start, int end, int step) {
    int n = start;
    while (n <= end) {
        yield n;
        n += step;
    }
}

つかいます:

foreach (int n in For(1, 200, 4)) {
    Console.WriteLine(n);
}

より多くの勝利のために、3つのデリゲートをパラメータとして取ることができます。


それは常に近くになります。 配列の場合、 時には forが少し速いですが、 foreachはより表現力があり、LINQなどを提供します。一般的に、 foreachます。

さらに、 foreachはいくつかのシナリオでは最適化されるかもしれません。 たとえば、リンクされたリストはインデクサーによってひどいかもしれませんが、 foreachによって素早くなるかもしれません。 実際、標準のLinkedList<T>では、この理由でインデクサーを提供していません。


ばかげてる。 for-loop、performance-wise、またはその他を禁止する魅力的な理由はありません。

パフォーマンスベンチマークとその他の議論については、 Jon Skeetのブログを参照してください。


まず、 ドミトリーの答えに対する反対請求。 配列の場合、C#コンパイラは、同等のforループと同じように、 foreachために大部分同じコードを出力forます。 つまり、このベンチマークの理由は基本的に同じです。

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 1000000;
    const int Iterations = 10000;

    static void Main()
    {
        double[] data = new double[Size];
        Random rng = new Random();
        for (int i=0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }

        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j=0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop: {0}", sw.ElapsedMilliseconds);
    }
}

結果:

For loop: 16638
Foreach loop: 16529

次に、コレクションの型が重要であることをGregが指摘していることを確認する - 配列を上記のList<double>に変更すると、根本的に異なる結果が得られます。 一般的にはかなり遅いだけでなく、索引によるアクセスよりもかなり遅くなります。 言いましたが、コードをよりシンプルにするforループのほうがforeachを好むでしょう。なぜなら、可読性はほとんど常に重要なのに対し、マイクロ最適化はまれであるからです。


より単純なロジックを実装するので、foreachより高速です。


パフォーマンス上の議論があるときはいつでも、あなたのケースをサポートするために定量結果を使用できるように、小さなテストを書くだけです。

StopWatchクラスを使用し、精度のために数百万回何かを繰り返します。 (これはforループなしでは難しいでしょう):

using System.Diagnostics;
//...
Stopwatch sw = new Stopwatch()
sw.Start()
for(int i = 0; i < 1000000;i ++)
{
    //do whatever it is you need to time
}
sw.Stop();
//print out sw.ElapsedMilliseconds

フィンガーはこの差異が無視できる程度であることを示しています。また、結果が最も保守的なコードであれば


両者のパフォーマンスに大きな違いはないでしょう。 いつものように、「より速いの? あなたはいつも「私はこれを測定することができる」と考えるべきです。

ループの本体で同じことをする2つのループを作成し、それらの両方を実行して時刻を合わせ、速度の違いを確認します。 ほとんど空のボディと、実際にやっているものと同様のループボディの両方でこれを行います。 また、異なるタイプのコレクションが異なるパフォーマンス特性を持つ可能性があるため、使用しているコレクションタイプで試してみてください。


彼の頭を本当にねじ込んで、代わりにIQueryable .foreach閉鎖に行く:

myList.ForEach(c => Console.WriteLine(c.ToString());


私の推測では、おそらく99%のケースではそれほど重要ではないだろう、なぜあなたは最も適切なものの代わりにより速く選択するのだろうか(理解しやすく維持するのが最も簡単なように)?


誰もが2つのパフォーマンスの違いが「巨大」であるとは思っていません。

私は、あなたがアクセスしようとしているコレクションがより高速なインデクサーアクセスの実装か高速のIEnumeratorアクセス​​の実装かどうかによって答えが変わってくると思います。IEnumeratorはしばしばインデクサーを使用し、現在のインデックス位置のコピーを保持するだけなので、列挙子アクセスは少なくとも直接インデックスアクセスよりも遅くても遅くても大丈夫だと思います。

もちろん、この答えは、コンパイラが実装できる最適化を考慮していません。


forループとforeachループは必ずしも等価ではないことに注意してください。リストの列挙子は、リストが変更された場合に例外をスローしますが、通常のforループで警告を受け取るとは限りません。間違った時間にリストが変わると、違う例外が出ることさえあります。





for-loop