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


19

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

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


2
問題は、保存する処理時間にどれだけ時間がかかり、より困難なメンテナンスに費やされる時間を渡すことです。それに対する答えは、アプリケーションに完全に依存します。
Blrfl

2
多くの良い質問は、専門家の経験に基づいてある程度の意見を生み出しますが、この質問に対する答えは、事実、参考文献、または特定の専門知識ではなく、意見にほぼ完全に基づく傾向があります。
gnat

10
また、関数呼び出しやメソッド呼び出しの計算ペナルティは非常に小さいため、多くの関数呼び出しやメソッド呼び出しがある非常に大きなプログラムであっても、それらの呼び出しがチャート上でランク付けされないことも
-greyfade

1
@greyfade:これは直接ジャンプには当てはまりますが、追加の間接予測ジャンプには、たとえばプログラムの合計実行時間の約3%がかかる場合があります(最近チェックしたプログラムからの数字だけです-代表的なものではないかもしれません)。あなたの地域に応じて、あなたはそれを重要であると考えるかもしれないし、そうでないかもしれないが、それはチャートに登録した(そしてもちろん、それはモジュール性に少なくとも部分的に直交している)。
マチェイピエチョトカ

4
早すぎる最適化はすべての悪の根源です。線形コードはモジュラーコードよりもわずかに高速です。モジュラーコードは、スパゲッティコードよりも非常に高速です。全体の非常に(非常に)完全なプロジェクトなしで線形コードを目指す場合、スパゲッティコードになります、私はそれを保証します。
SF。

回答:


46

はい、関係ありません。

コンピューターは、脳に比類のない速度で動作する、疲れ知らずでほぼ完璧な実行エンジンです。関数呼び出しがプログラムの実行時間に追加する測定可能な時間はありますが、これは、読み取り不能なルーチンを解きほぐす必要があるときに、コードに関与する次の人の脳が必要とする追加時間と比較して何もありませんそれをどのように使うかを理解し始めることさえできます。ジョークの計算を試してみることができます。コードを1回だけ保守する必要があると仮定すると、誰かがコードに同意するのに必要な時間に30分しか追加されません。プロセッサーのクロック速度を計算して、それを相殺することを夢見るためにコードを何回実行する必要があるでしょうか?

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


2
ほとんどの場合、時期尚早な最適化であることに同意しますが、時間に関するあなたの議論は悪いと思います。時間はさまざまな状況で相対的であり、あなたが行ったように単純に計算することはできません。
ホンザブラベック

28
「CPUに同情する」という表現のためだけに+1。
マイケルボルグワード

4
関連性が高い: コンピューターは日常的にどのくらいの速度ですか? 「スピード」のためのいくつかの関数呼び出しを避けるためにあなたの邪魔をすることは、あなたの人生全体にわたって誰かを合計1分節約するためにあなたの邪魔をするようなものです。要するに、検討するのに時間を費やす価値すらありません。
BlueRaja-ダニーPflughoeft

7
足りないものを非常に雄弁に販売するために+1を追加しましたが、CPUの哀れみをさらに深刻にするバランスに最も重要な重みを追加するのを忘れました。その1回のメンテナンスに費やした時間と損失を無視します。1秒かかったとしても、そこにははるかに潜んでいるシンクがまだあります。バグリスク。後のメンテナーがコードを変更するのがより複雑で困難なほど、彼がその中にバグを実装するリスクがより大きくなり、ユーザーへのリスクからの不可避的に大きな避けられないコストを引き起こし、バグが後続のメンテナンスを引き起こす可能性がありますバグ...)
ジミーホッファ

私の昔の先生は、「あなたが時期尚早に最適化しているかどうかを考えているなら、ここでやめてください。これが正しい選択なら、あなたはそれを知っていたでしょう」と言いました。
ヴェン

22

場合によります。

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

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

数年前、私はリアルタイムFLIR画像で、当時はまともなプロセッサであった非再帰的な8ウェイ接続BLOBカラーリングを行っていました。最初の試行ではサブルーチン呼び出しが使用され、サブルーチン呼び出しのオーバーヘッドにより、プロセッサが生きていました。(4コールPERピクセルxフレームあたり64Kピクセルx秒あたり30フレーム=それを把握します)。2回目の試行では、サブルーチンがCマクロに変更され、読みやすさが損なわれず、すべてがバラになりました。

あなたは何をしているのか、そしてあなたがそれをしている環境でHARDを見る必要があります。


最新のプログラミング問題の大部分は、多くのオブジェクト指向のメソッドハッピーコードに最もよく対処することを忘れないでください。組み込みシステム環境にいることを知ることができます。
ケビン-モニカ

4
+1。ただし注意が必要です。通常、最適化コンパイラは、人よりもインライン化、ループの展開、スカラーおよびベクトルの最適化を行うという点で優れています。プログラマーは、これを利用するために言語、コンパイラー、およびマシンを非常によく知る必要があるため、魔法ではありません。
間違いなく

2
それは事実ですが、ロジックを記述し、アルゴリズムで問題のある部分を見つけるためにプロファイルを作成した、コードを最適化しました。パフォーマンスのためではなく、読みやすさのためにコーディングを開始していません。また、マクロはコードを読みやすくするのに役立ちます。
ウーヴェプロナス

2
組み込みシステムは、プログラミングにおいても、明確な正しいコードを書き込むことによって開始し、唯一その後最適化を開始必要に応じ及びプロファイリングによって案内されるよう。そうしないと、パフォーマンス/コードサイズに実際の影響を与えず、ソースを理解しにくくするだけの大量の作業を行うのが簡単すぎます。
ドナルドフェローズ

1
@detly:はい、いいえ。現代のコンパイラは、一般に、言語によって課された制限内でより良い仕事をすることができます。人間のプログラマは、言語によって課せられた制限が特定のケースに適用できるかどうかを知っています。たとえば、プログラマが特定の非常に病理学的なことを行い、とにかく動作するコードを生成できるようにするには、言語標準でCnおよびC ++コンパイラが必要です。プログラマーは、自分がそのようなことをするほどクレイジーでも愚かでも冒険的でもないことを知り、そうでなければ安全ではない最適化を行います。
ジョンR.ストローム

11

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

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

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


5
他の人が理解できるような方法でプログラムを書くべきだと思います。
バルトロミエレヴァンドフスキ

プログラムを最初に読まなければならないのは開発者自身です。それが私があなたを書いた理由です。他の人もプログラムを読むことができればそれは素晴らしいですが、(私の目には)必要ではありません(そもそも)。あなたがチームで働いている場合、他の人もプログラムを理解する必要がありますが、私の意図は、コンピュータではなくプログラムを読む必要があるということでした。
ウーヴェプロナス

5

あなたはそれ以外の場合は、大きな機能を持っているでしょうし、あなたがより小さなものの多くに分割したときに一般的に、これらの小さいものがされますインライン化(あまり同じ指示を繰り返す)インライン化の唯一の欠点は、この場合は関係ありませんので。つまり、コードは1つの大きな関数を記述したかのように動作します。

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


2

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

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

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

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

マイクロ最適化を実行する必要があると判断した場合(実際には、ソフトウェアがHPCで使用されるか、組み込みで使用されるか、非常に多くの人々が使用することを意味します-そうでない場合は、メンテナンスの追加コストがコンピューターの時間コストを克服します)高速化するホットスポット(カーネル)を特定します。しかし、その後、おそらくあなたはすべきです:

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

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

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

0

私の答えは、おそらく既存の答えではあまり拡大しませんが、2セントが役立つと思います。

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

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

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

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


0

はいといいえ。他の人が最初に読みやすさのためのプログラムに言及したように、次に効率のために。ただし、読みやすく効率的な標準プラクティスがあります。ほとんどのコードはかなり頻繁に実行されますが、とにかく最適化してもそれほど利点は得られません。

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

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

コードを最適化する価値がある場合もありますが、一般に、コードをプロファイリングしてどこにあるかを判断する必要があります。多くの場合、期待したコードではないことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.