web-dev-qa-db-ja.com

モジュール式プログラミングは計算時間に影響しますか?

私は自分のコードをモジュール化する必要があると誰もが言っていますが、メソッドの呼び出しを少なくするが、大きくするよりも、メソッドの呼び出しを多く使用すると効率が低下しませんか?その点で、Java、C、またはC++の違いは何ですか?

特にグループでは、編集、読み取り、理解が簡単になると思います。それでは、コードの整頓の利点と比較して、計算時間の損失は重要ではありませんか?

19
fatsokol

はい、それは無関係です。

コンピュータは、脳とはまったく比較にならない速度で動作する、疲れのない、ほぼ完璧な実行エンジンです。関数呼び出しがプログラムの実行時間に追加する測定可能な時間はありますが、これは、コードに関係する次の人が読めないルーチンを解く必要があるときに頭脳が必要とする追加の時間と比較して何もありませんにbeginを使用して作業する方法を理解します。あなたは冗談のために計算を試すことができます-あなたのコードはonceだけを維持する必要があると仮定し、それはonly誰かが来るのに必要な時間に30分を追加しますコードとの契約に。プロセッサのクロック速度を計算して計算します。コードは、dreamオフセットするまで何回実行する必要がありますか?

要するに、CPUに同情することは、時間の99.99%を完全に、見当違いにしています。残りのまれなケースでは、プロファイラーを使用します。してくださいnotそれらのケースを見つけることができると仮定します-あなたはできません。

46
Kilian Foth

場合によります。

すべてが人間の速度で行われるWebプログラミングという氷河のように遅い世界では、メソッド呼び出しのコストがメソッドによって実行される処理のコストに匹敵するかそれを超える、メソッドを多用したプログラミングはおそらく問題ではありません。 。

組み込みシステムのプログラミングと高速割り込み用の割り込みハンドラーの世界では、それが最も重要です。その環境では、「メモリアクセスは安価」と「プロセッサは無限に速い」という通常のモデルが機能しなくなります。メインフレームのオブジェクト指向プログラマーが最初の高速割り込みハンドラーを作成するとどうなるかを見てきました。きれいじゃなかった。

数年前、当時のまともなプロセッサーであったリアルタイムFLIR画像で、非再帰的な8ウェイ接続BLOBカラーリングを行っていました。最初の試みはサブルーチン呼び出しを使用しており、サブルーチン呼び出しのオーバーヘッドによりプロセッサが生き残りました。 (4がPER PIXELを呼び出すx 1フレームあたり64Kピクセルx 1秒あたり30フレーム=計算する) 2番目の試みは、可読性を失うことなく、サブルーチンをCマクロに変更し、すべてがバラでした。

あなたは自分がやっていることとそれをやろうとしている環境を厳しく見なければなりません。

22
John R. Strohm

まず第一に、高級言語のプログラムは、機械ではなく人間が読むためのものです。

あなたが理解できるようにプログラムを書いてください。パフォーマンスについて考えないでください(パフォーマンスの問題が深刻な場合は、アプリケーションのプロファイルを作成し、必要な場所でパフォーマンスを向上させます)。

メソッドまたは関数の呼び出しに多少のオーバーヘッドがかかることは事実ですが、これは問題になりません。今日のコンパイラーは、コードを効率的な機械語にコンパイルして、生成されたコードがターゲットアーキテクチャに対して効率的になるようにする必要があります。コンパイラの最適化スイッチを使用して、効率的なコードを取得します。

11
Uwe Plonus

通常、そうでなければ大きな関数があり、それを多数の小さな関数に分割する場合、これらの小さな関数は inlined になります。この場合。つまり、コードは1つの大きな関数を作成したかのように動作します。

何らかの理由でインライン化されておらず、これがパフォーマンスの問題になる場合は、手動でインライン化することを検討してください。すべてのアプリケーションがネットワーク化されたCRUDフォームであり、固有のレイテンシが非常に大きいわけではありません。

5
Esailija

おそらく計算コストは​​ありません。通常、過去10〜20年程度のコンパイラー/ JITは、関数を完全にインライン化して処理します。 C/C++の場合、通常は「インライン化可能な」関数に制限されます(つまり、関数の定義はコンパイル時にコンパイラーで使用できます-つまり、同じファイルのヘッダーにあります)が、LTOの現在の手法はこれを克服します。

最適化に時間を費やす必要があるかどうかは、作業している領域によって異なります。入力の待機にほとんどの時間を費やした「通常の」アプリケーションを扱う場合、アプリケーションの「速度が遅い」と感じない限り、最適化について心配する必要はないでしょう。

このような場合でも、マイクロ最適化を行う前に多くのことに集中する必要があります。

  • 問題はどこにありますか?通常、ソースコードを別の方法で読んでいるため、ホットスポットを見つけるのに苦労しています。動作時間の比率は異なり、順次 modernprocessorsdo n't の間実行します。
  • 毎回計算が必要ですか?たとえば、数千のうち1つのパラメータを変更する場合、モデル全体ではなく影響を受ける部分のみを計算することができます。
  • 最適なアルゴリズムを使用していますか? O(n)からO(log n)への変更は、マイクロ最適化によって達成できるものよりもはるかに大きな影響を与える可能性があります。
  • 適切な構造を使用していますか? Listが必要なときにHashSetを使用しているので、O(n)を使用できる場合はO(1)ルックアップを使用するとします。
  • 並列処理を効率的に使用していますか?現在、携帯電話でさえ4コア以上を持つことができ、スレッドを使用したくなるかもしれません。ただし、同期のコストがあるため、これらは特効薬ではありません(問題がメモリにバインドされている場合は、とにかく意味がありません)。

マイクロ最適化を実行する必要があると判断した場合でも(実際には、ソフトウェアがHPCで使用されているか、埋め込まれている、またはveryによって使用されているだけです)人の数-それ以外の場合は、追加のメンテナンスコストがコンピューターの時間コストを克服します)加速したいホットスポット(カーネル)を特定する必要があります。しかし、おそらく次のことを行う必要があります。

  1. 作業しているプラ​​ットフォームを正確に把握する
  2. 作業しているコンパイラー、コンパイラーが実行できる最適化、およびそれらの最適化を有効にする慣用的なコードの記述方法を正確に把握する
  3. メモリアクセスパターンと、キャッシュにどれだけ収まるかを考えます(ポイント1からわかる正確なサイズ)。
  4. 次に、計算限界がある場合は、計算を保存して計算を再編成することを検討してください。

最後の発言として。通常、メソッド呼び出しで発生する唯一の問題は、分岐予測子によって予測されなかった間接ジャンプ(仮想メソッド)です(残念ながら、間接ジャンプが難しいケースです)。しかしながら:

  • JavaにはJITがあり、多くの場合、クラスのタイプ、したがってジャンプのターゲットを事前に予測できるため、ホットスポットでは多くの問題が発生しないはずです。
  • C++コンパイラは多くの場合、プログラム分析を実行し、少なくとも一部のケースでは、コンパイル時にターゲットを予測できます。
  • どちらの場合も、ターゲットが予測されていれば、インライン化が機能するはずです。コンパイラーがインライン化の機会を実行できなかった場合、私たちもできませんでした。
2

私の答えはおそらく既存の答えをあまり拡張しませんが、私の2セントは役に立ちそうな気がします。

最初に;はい、モジュール化のために、通常はある程度の実行時間をあきらめます。アセンブリコードですべてを記述すると、最高の速度が得られます。それは言った...

YouTubeを知っていますか?おそらく、存在する最も高帯域幅のサイトか、Netflixに次ぐサイトか?彼らはコードの大部分をPythonで記述します。Pythonは非常にモジュール化された言語であり、一流のパフォーマンスを実現するために構築されていません。

問題は、何かがうまくいかず、ユーザーが動画の読み込みに時間がかかるという不満がある場合、その速度の低下が最終的にはPythonの実行速度が遅いことに起因するシナリオは多くありません。ただし、Pythonの迅速な再コンパイルと、型チェックを行わずに新しいことを試すことができるモジュラー機能により、エンジニアは問題の原因をかなり迅速にデバッグできるようになります(「うわ。新しいインターンは、新しいSQLサブクエリを実行するループを作成しました。すべての結果。 ")または("ああ、Firefoxは古いキャッシュヘッダー形式を非推奨にしています。また、Pythonライブラリを作成して、新しいものを簡単にセットアップできます ")

その意味で、実行時間の観点からも、ボトルネックが何であるかを見つけたら、コードを再編成して最適な方法で機能させることが容易になるため、モジュラー言語はより高速であると考えることができます。そのため、多くのエンジニアは、パフォーマンスの大きな影響が予想した場所ではなかった(そして実際には、DID最適化がほとんど必要なかった、または機能しなかった)と言うでしょう。彼らが期待する方法!)

0
Katana314

はいといいえ。他の人が最初に読みやすさ、次に効率性のためにプログラムを指摘したように。ただし、読みやすく効率的な標準的な方法があります。ほとんどのコードが実行される頻度はかなり低いため、とにかくそれを最適化してもあまりメリットはありません。

Javaは小さな関数呼び出しをインライン化できるため、関数の記述を避ける理由はほとんどありません。オプティマイザは、シンプルで読みやすいコードでよりよく機能する傾向があります。理論的にはより速く実行され、実際にはより長くかかるショートカットを示す研究があります。 JITコンパイラーは、コードが小さく、頻繁に実行される部分を識別して最適化できるため、より適切に機能する可能性があります。私はそれを試していませんが、比較的まれに呼び出される大きな関数がコンパイルされないことを期待します。

これはおそらくJavaには当てはまりませんが、ある研究では、異なるメモリ参照モデルが必要なため、大きな関数の実行速度が実際に遅くなることがわかりました。これはハードウェアとオプティマイザ固有のものでした。小さいモジュールの場合、メモリページ内で機能する命令が使用されました。これらは、関数がページに収まらない場合に必要な指示よりも高速で小さくなりました。

コードを最適化する価値がある場合もありますが、一般的には、どこにあるかを判断するためにコードをプロファイルする必要があります。私が期待するコードではないことがよくあります。

0
BillThor