36

に比べ

  • シンプルなメモリアクセス
  • ディスクアクセス
  • 別のコンピュータ (同じネットワーク上) でのメモリ アクセス
  • 別のコンピュータ (同じネットワーク上) でのディスク アクセス

Windows 上の C++ で。

4

15 に答える 15

30

相対的なタイミング (100 倍以上ずれてはいけません ;-)

  • キャッシュ内のメモリ アクセス = 1
  • キャッシュ内の関数呼び出し/リターン = 2
  • キャッシュからのメモリアクセス = 10 .. 300
  • ディスク アクセス = 1000 .. 1e8 (償却は、転送されたバイト数に依存します)
    • 主にシーク時間に依存
    • 転送自体はかなり高速です
    • ユーザー/システムのしきい値を少なくとも 2 回超える必要があるため、少なくとも数千の操作が必要です。I/O 要求をスケジュールする必要があり、結果を書き戻す必要があります。おそらくバッファが割り当てられています...
  • ネットワーク呼び出し = 1000 .. 1e9 (償却は、転送されたバイト数によって異なります)
    • ディスク i/o と同じ引数
    • 生の転送速度は非常に高速になる可能性がありますが、他のコンピューターの一部のプロセスが実際の作業を行う必要があります
于 2008-09-18T18:07:01.420 に答える
19

関数呼び出しは、メモリ内のフレーム ポインターをスタックにシフトし、その上に新しいフレームを追加するだけです。関数パラメータは使用のためにローカル レジスタにシフトされ、スタック ポインタは関数の実行のためにスタックの新しいトップに進められます。

時間に比べて

関数呼び出し ~ 単純なメモリ アクセス
関数呼び出し < ディスク アクセス
関数呼び出し < 別のコンピュータのメモリ アクセス 関数呼び出し < 別のコンピュータ
のディスク アクセス

于 2008-09-18T17:43:55.877 に答える
8

単純なメモリアクセスと比較して、わずかに多く、実際には無視できます。

リストされている他のすべてのものと比較して、桁違いに少ない.

これは、どの OS のほぼすべての言語にも当てはまります。

于 2008-09-18T17:42:44.397 に答える
4

一般に、関数呼び出しは実際には呼び出しを実行するために複数のメモリ アクセスを行う必要があるため、メモリ アクセスよりもわずかに遅くなります。たとえば、x86 で __stdcall を使用するほとんどの関数呼び出しでは、スタックのプッシュとポップを複数回行う必要があります。ただし、メモリ アクセスが L2 キャッシュにさえないページに対するものである場合、宛先とスタックがすべて CPU のメモリ キャッシュにあれば、関数呼び出しははるかに高速になります。

それ以外の場合は、関数呼び出しの方がはるかに高速です。

于 2008-09-18T17:44:32.893 に答える
3

いろいろな要素が絡むので答えにくいです。

まず、「単純なメモリアクセス」は単純ではありません。現代のクロック速度では、CPU はチップの一方の側から他方の側に数値を取得するよりも速く 2 つの数値を加算できるため (光の速度 -- これは単なる良い考えではなく、法則です)

では、関数は CPU メモリ キャッシュ内で呼び出されているのでしょうか。あなたもそれを比較しているメモリアクセスですか?

次に、関数呼び出しで CPU 命令パイプラインをクリアします。これは非決定的な方法で速度に影響します。

于 2008-09-18T17:47:19.690 に答える
3

呼び出し先が何をするかではなく、呼び出し自体のオーバーヘッドを意味すると仮定すると、「単純な」メモリアクセス以外のすべてよりもはるかに高速です。

おそらくメモリ アクセスよりも遅くなりますが、コンパイラはインライン化できるため、関数呼び出しのオーバーヘッドがゼロになる場合があることに注意してください。そうでない場合でも、少なくとも一部のアーキテクチャでは、既に命令キャッシュにあるコードへの呼び出しが、メイン (キャッシュされていない) メモリにアクセスするよりも高速になる可能性があります。それは、呼び出しを行う前にスタックにスピルする必要があるレジスタの数、およびそのようなものに依存します。出力されたコードを逆アセンブルするよりも早く解決できる可能性は低いですが、コンパイラと呼び出し規約のドキュメントを参照してください。

また、「単純な」メモリアクセスはそうでない場合があることに注意してください-OSがディスクからページを取得する必要がある場合、長い待ち時間が発生します。現在ディスク上でページアウトされているコードにジャンプする場合も同様です。

根底にある質問が「実行される関数呼び出しの総数を最小限に抑えるためにコードを最適化する必要があるのはいつですか?」である場合、答えは「まったくないに近い」です。

于 2008-09-18T17:53:44.777 に答える
2

このリンクは Google でよく出てきます。今後の参考のために、関数呼び出しのコストについて C# で短いプログラムを実行したところ、「インラインの約 6 倍のコスト」という答えが返ってきました。以下に詳細を示します。下部の //Output を参照してください。更新: リンゴとリンゴをよりよく比較するために、Class1.Method を変更して「void」を返すようにしました。それでも
、インラインは 2 倍高速です: インライン (平均): 610 ミリ秒; 関数呼び出し (平均): 1380 ミリ秒。したがって、更新された答えは「約2回」です。

システムを使用して; System.Collections.Generic の使用; System.Linq を使用します。System.Text を使用します。System.Diagnostics を使用します。

名前空間 FunctionCallCost { クラス プログラム { static void Main(string[] args) { Debug.WriteLine("stop1"); int iMax = 100000000; //100M DateTime funcCall1 = DateTime.Now; ストップウォッチ sw = Stopwatch.StartNew();

        for (int i = 0; i < iMax; i++)
        {
            //gives about 5.94 seconds to do a billion loops, 
          // or 0.594 for 100M, about 6 times faster than
            //the method call.
        }

        sw.Stop(); 

        long iE = sw.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of main function (ms) is: " + iE.ToString());

        Debug.WriteLine("stop2");

        Class1 myClass1 = new Class1();
        Stopwatch sw2 = Stopwatch.StartNew();
        int dummyI;
        for (int ie = 0; ie < iMax; ie++)
        {
          dummyI =  myClass1.Method1();
        }
        sw2.Stop(); 

        long iE2 = sw2.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of helper class function (ms) is: " + iE2.ToString());

        Debug.WriteLine("Hi3");


    }
}

// System を使用したクラス 1; System.Collections.Generic の使用; System.Linq を使用します。System.Text を使用します。

名前空間 FunctionCallCost { クラス Class1 {

    public Class1()
    {
    }

    public int Method1 ()
    {
        return 0;
    }
}

}

// 出力: メイン関数の stop1 経過時間 (ms): 595 ヘルパー クラス関数の stop2 経過時間 (ms): 3780

メイン関数の stop1 経過時間 (ms): 592 ヘルパー クラス関数の stop2 経過時間 (ms): 4042

メイン関数の stop1 経過時間 (ms): 626 ヘルパー クラス関数の stop2 経過時間 (ms): 3755

于 2010-03-04T20:36:54.267 に答える
1

C++ には仮想呼び出し (かなり高価で、約 x10) があり、Windows では VS が呼び出しをインライン化することを期待できることを忘れないでください (バイナリに呼び出しが残っていないため、定義によりコストはゼロです)。

于 2008-09-19T11:28:43.023 に答える
1

関数を実際に呼び出すが、完全に実行しない場合のコストは? または実際に機能を実行するコストは?関数呼び出しを設定するだけでは、コストのかかる操作ではありません (PC を更新しますか?)。しかし明らかに、関数を完全に実行するコストは、関数が何をしているかによって異なります。

于 2008-09-18T17:48:55.723 に答える
0

関数呼び出しは、実際にはスタックへのパラメーターのコピー(複数のメモリアクセス)、レジスタの保存、実際のコードの実行、そして最後に結果のコピーとレジスタの復元です(レジスタの保存/復元はシステムによって異なります)。

だから..比較的話す:

  • 関数呼び出し>単純なメモリアクセス。
  • 関数呼び出し<<ディスクアクセス-メモリと比較すると、数百倍も高価になる可能性があります。
  • 関数呼び出し<<別のコンピューターでのメモリアクセス-ネットワーク帯域幅とプロトコルは、ここでは非常に重要です。
  • 関数呼び出し<<<別のコンピューターでのディスクアクセス-上記のすべておよびそれ以上:)
于 2008-09-18T19:07:19.530 に答える
0

メモリーアクセスのみが関数呼び出しよりも高速です。

ただし、インライン最適化を使用するコンパイラー(GCCコンパイラーの場合、レベル3の最適化(-O3)を使用するときにアクティブ化されるだけでなく)を使用すると、呼び出しを回避できます。

于 2008-09-18T19:10:23.843 に答える
0

関数呼び出しのコストは、アーキテクチャによって異なります。x86はかなり低速ですが(関数の引数ごとに数クロックと1クロック程度)、64ビットは、ほとんどの関数の引数がスタックではなくレジスタで渡されるため、はるかに低速です。

于 2008-09-18T18:10:54.873 に答える
0

その関数が何をするかによって異なりますが、メモリ内のオブジェクトでロジックを実行している場合、リストの 2 番目になります。ディスク/ネットワーク アクセスが含まれている場合は、リストのさらに下に移動します。

于 2008-09-18T17:42:35.940 に答える
0

通常、関数呼び出しには、2、3 のメモリ コピー (多くの場合、レジスタへのコピーであるため、それほど時間はかからないはずです) と、その後のジャンプ操作のみが含まれます。これはメモリ アクセスよりも遅くなりますが、他のハードウェアとの通信が必要なため、上記の他の操作よりも高速です。通常、どの OS と言語の組み合わせでも同じことが当てはまります。

于 2008-09-18T17:46:22.873 に答える
0

関数がコンパイル時にインライン化されている場合、関数のコストは 0 と同等になります。

0 もちろん、関数呼び出しを持たないことで得られるもの、つまり自分でインライン化したものです。

もちろん、私がそのように書くと、これは過度に明白に聞こえます。

于 2008-09-18T17:46:42.437 に答える