大規模なソフトウェアプロジェクトの実際の複雑さを測定する方法は?


11

大学のアルゴリズムコースでは、ハッシュテーブルやクイックソートなど、実際に使用されるさまざまな単純なアルゴリズムの複雑さを正確に計算する方法を学びます。

しかし、今では大規模なソフトウェアプロジェクトで、より高速にしたい場合は、個々のピースを見るだけです-いくつかのネストされたループは、より高速なハッシュテーブルに置き換えられます。より洗練された手法ですが、パイプライン全体の複雑さを計算することはありません。

それを行う方法はありますか?または、実際には、アプリケーション全体をグローバルに考慮するのではなく、アプリケーション全体を高速化するために、高速アルゴリズムを使用して「ローカル」に依存しているだけでしょうか?

(私自身は非常に高速であることが知られている多数のアルゴリズムを積み重ねると、全体として高速なアプリケーションになってしまうことを示すのは自明ではないように思えます。)

他の誰かが書いた大規模なプロジェクトを高速化することを任されているため、私はこれを求めていますアプリケーション全体。


1)これには、改善するポイントを見つけるためのテストアプローチが必要です。ベンチマークテスト、耐久性テスト、動的テスト(各コンポーネントのメモリ/ CPUメトリックの監視による)。2)改善するポイントを見つけたら、それらのポイントの根本原因を見つけます。3)正確性を維持しながら、根本原因を解決する解決策を見つけます。
過剰交換

ポイント1で述べたこれらのテストにはいくつかのツールが必要です
18年

1
Big O分析では、アルゴリズムの実行方法はわかりません。これは、パフォーマンスがする方法を説明しますスケールとして、n増加しています。
ジョン・ウー

回答:


5

大規模なソフトウェアプロジェクトは多くの異なるコンポーネントで構成されており、それらのすべてが通常ボトルネックではありません。まったく逆:パフォーマンスが低いことが問題であった私の人生のほとんどすべてのプログラムで、パレートの原則が適用されました:コードの20%未満を最適化することでパフォーマンスの80%以上を実現できます(実際には、多くの場合、数字は95%〜5%だったと思います)。

そのため、多くの場合、個々のピースを調べ始めることが最善のアプローチです。これがプロファイリング(David Arnoの回答で説明されている)がうまくいく理由です。最適化により「最大の価値」が得られるコードの5%を特定するのに役立ちます。「アプリケーション全体」を最適化すると、オーバーエンジニアリングの特定のリスクが生じます。10倍でも95%を最適化しても、測定可能な効果はほとんどありません。また、プロファイリングは、O(N ^ 3)ステップを必要とする単純なアルゴリズムが、N(O十分に小さいです。

プロファイリングでホットスポットが明らかになったら、それらを最適化できます。もちろん、「ホットスポット」は1行または2行のコードよりも大きくなる場合があり、コンポーネント全体を置き換えて高速化する必要がある場合もありますが、通常、それは大規模なプログラムのコードベースのごく一部です。

典型的な最適化手法には、

  • アルゴリズムとデータ構造の使用を改善する

  • 前者の微調整

  • いくつかの実際のホットスポットでのマイクロ最適化

  • アセンブリコードまたはCUDAを使用してクリティカルセクションを再コーディングする

これらの手法はさまざまな抽象化レベルで機能しており、一部の手法は他の手法よりも「全体として」コンポーネントを表示していることに注意してください。したがって、「個々のピースを見るだけ」という意味に依存します。マイクロ最適化のみを念頭に置いている場合、「私たち」はそれだけで作業することに同意しません。しかし、孤立した部品やコンポーネントにこれらの全面的な最適化を適用することを意味する場合、「私たち」はおそらく正しい部品に取り組んでいるので、期待に疑問を呈する必要があります。


13

標準的な、試行され、テストされた方法は、コードプロファイルすることです。実行中のシステムの動的分析を実行して、タイミング、メモリ使用量などを測定します。次に、結果を分析してパフォーマンスのボトルネックを見つけます。

次に、これらのボトルネックを実験的に書き直し、結果​​をもう一度プロファイリングして、速度の増加、メモリ使用量の削減などが達成されたことを確認します。このプロセスは、許容可能なパフォーマンスの向上が達成されるまで繰り返されます。


1
これはパフォーマンスの問題を解決します。それが私たちがそれを行う理由ですが、元の質問には答えません。特に、最悪の場合の時間またはスペースの複雑さは、静的プログラム分析ツールを使用することで最もよく理解できると思います。パフォーマンステストは特定のシナリオには適していますが、最悪の状況については多くを語りません。
フランクヒルマン

3
@FrankHilemanここでのポイントは、パフォーマンスは実際的な問題であり、実際にしか測定できないということだと思います。ソフトウェアのボトルネックを見つけるために数学を使用することはありません。一度数学(アルゴリズム)を使用して見つけたとしても、それを解決する場合があります。
ワイルドカード

関連する注意事項として、昔のスライドショープレゼンテーション(ガラススライド)では、使用する光の明るさを決定するためにランタンスライドの平均密度を苦労して計算する方法の全体的な技術がありました。完全に役に立たない:画像がうまく表示されない場合、より明るい光を得る!
ワイルドカード

@Wildcardパフォーマンスは実行時にのみ測定できますが、静的に予測できます。データ構造の不適切な選択は、パフォーマンステストでは見栄えが良くなりますが、静的分析で予測できるエッジケースでは悲惨に失敗する可能性があります。これは、一般的なデータ構造の最悪の場合の複雑性分析を検討するのと同じ理由です。
フランクヒルマン

@Wildcard:あなたは正しいですが、フランクはこの投稿が質問に答えないことも非常に正しいです。
ドックブラウン

3

他の答えは正解であり、いくつかのガイダンスを提供しますが、私は彼らが一歩を逃したと思います。現在作業しているような複雑なシステムでは、システムを構成するさまざまなコンポーネントを理解することが、何かが遅い理由を理解するための鍵となります。

私の最初のステップは、詳細なアーキテクチャ図を手に入れるか、自分で作成することです。ソフトウェアのどのコンポーネントがどのステップを実行するか、各ステップにかかる時間を把握します。

また、コンポーネントが互いにどのように相互作用するかを把握します。これはすべての違いを生むことができます。

たとえば、2つのコンポーネント間のインターフェイスが最初のコンポーネントで作成されたIEnumerableを渡し、2番目のコンポーネントで列挙されたC#のコードを見てきました。C#では、これにはコンテキストの切り替えが必要であり、特定の状況ではコストがかかる場合があります。解決してもアルゴリズムには影響しません。単純な.ToList()は、次のステップでこの問題を解決する前に結果が収集されることを確認します。

考慮すべきもう1つのことは、コードを実行しているシステムへの影響です。複雑なシステムでは、ハードウェアの相互作用が明らかに要因になることがあります。ディスクIO、大容量メモリの割り当て、およびネットワークIOを探します。システムを微調整したり、ハードウェアを交換することで、これらをより効率的に解決できる場合があります。

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