私は大学で運動を割り当てられました。私はそれを家に持ち帰り、それを解決するためのアルゴリズムをプログラムしようとしました。
それから、私が思いついた最も些細なことを作り、講師に見せました。簡単な観察の後、彼は私のソリューションの実行時の複雑さは実現不可能であり、より効率的なものを示していると感じました。そして、計算の複雑さについて何も知らないプログラマーの伝統があります(私はそれらの1つでした)。
私は大学で運動を割り当てられました。私はそれを家に持ち帰り、それを解決するためのアルゴリズムをプログラムしようとしました。
それから、私が思いついた最も些細なことを作り、講師に見せました。簡単な観察の後、彼は私のソリューションの実行時の複雑さは実現不可能であり、より効率的なものを示していると感じました。そして、計算の複雑さについて何も知らないプログラマーの伝統があります(私はそれらの1つでした)。
回答:
はい、計算の複雑さについて何かを知ることは、真面目なプログラマーにとって必須です。巨大なデータセットを扱っていない限り、複雑さを知らなくても問題ありませんが、深刻な問題に取り組むプログラムを作成したい場合は必要です。
特定のケースでは、接続されたコンポーネントを見つける例は、最大個のノードのグラフで機能した可能性があります。ただし、100.000ノードのグラフを試した場合、講師のアルゴリズムはおそらく1秒でそれを管理できたでしょうが、アルゴリズムは(複雑さの程度に応じて)1時間、1日、または場合によっては1永遠にかかっていました。
学生がアルゴリズムコースで行うよくある間違いは、次のような配列を繰り返すことです。
while array not empty
examine first element of array
remove first element from array
これは最も美しいコードではないかもしれませんが、複雑なプログラムでは、プログラマが気付かないうちにこのようなものが表示される可能性があります。さて、このプログラムの問題点は何ですか?
while array not empty
examine last element of array
remove last element from array
これは単なるおもちゃの例ですが、すでに2つのプログラムの違いを伝えるために複雑さの基本的な理解が必要です。実際に、この間違いのあるより複雑なプログラムをデバッグ/最適化しようとする場合、見つけるにはさらに大きな理解が必要ですバグがどこにあるか。というのも、この方法で配列から要素を削除するような間違いは、コードの抽象化によって非常によく隠れるからです。
複雑さをよく理解することは、2つのアプローチを比較して問題を解決するときにも役立ちます。接続コンポーネントの問題を自分で解決するための2つの異なるアプローチを考え出したと仮定します。それらを決定するために、それらの複雑さを(迅速に)推定し、より良いものを選択できれば非常に便利です。
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
これはしばしば真実ですが、常にそうではありません。たとえばO(n!)
、比較的小さなデータセットであっても、アルゴリズムは実行できません。プログラムをO(n!)
使用できるアルゴリズムを使用するとO(n^2)
、10のデータサイズで実行するのに36,288倍の時間がかかります。データサイズが20の場合、2.4五十億操作を検討しています。
これはTom van der Zandenの答えの反論であり、これは必須であると述べています。
問題は、ほとんどの場合、50.000倍遅いことは関係ありません(もちろん、Googleで働いている場合を除きます)。
実行する操作にマイクロ秒かかる場合、またはNが特定のしきい値(最近行われたコーディングの大部分)を超えない場合、それは重要ではありません。そのような場合、計算の複雑さについて考えることは、時間(そしておそらくお金)を無駄にするだけです。
計算の複雑さは、何かが遅くなったり、スケールが悪くなったりする理由と、それを改善する方法を理解するためのツールですが、ほとんどの場合、完全にやり過ぎです。
私はもう5年以上プロのプログラマーであり、ループO(M * N)内でループするときに計算の複雑さを考える必要性は一度もありません。小さい。
プログラミングジョブを実行する人にとっては、はるかに重要で一般的に使用され、理解しにくいものがあります(パフォーマンス領域では、スレッド化とプロファイリングが良い例です)。
もちろん、計算の複雑さを理解しないとできないことはいくつかあります(たとえば、辞書でアナグラムを見つける)が、ほとんどの場合は必要ありません。
私はソフトウェアの開発を約30年間行っており、請負業者と従業員の両方として働いており、かなり成功しています。私の最初の言語はBASICでしたが、私はすぐに機械語を学び、力不足のボックスから適切な速度を引き出すようにしました。私は長年プロファイラーで多くの時間を費やし、高速でメモリ効率の高い最適化されたコードの生成について多くを学びました。
言うまでもなく、私は独学です。数年前にインタビューを開始するまで、O表記に出会うことはありませんでした。インタビュー中を除いて、私のプロの仕事では決して出てきません。そのため、インタビューでその質問を処理するためだけに基本を学ばなければなりませんでした。
楽譜を読むことができないジャズミュージシャンのように感じます。私はまだうまくプレイできます。私はハッシュテーブル(つまり、ハッシュテーブルはすでに発明されていることを知る前に発明しました)およびその他の重要なデータ構造について知っています。しかし、真実は、この職業で成功するためには、インディーズに行くか、インタビュー中に彼らが尋ねる質問に対する答えを学ぶ必要があるということだと思います。
ちなみに、私は最近、フロントエンドのWeb開発者の役割についてインタビューしました。彼らは、答えが計算の複雑さと対数の両方の知識を必要とする質問をしました。私は20年前の数学を多かれ少なかれ正確に答えるのに十分なほど覚えていましたが、少し耳障りでした。フロントエンドの開発で対数を使用する必要はありません。
頑張って!
質問は非常に主観的であるため、答えはそれが依存することだと思います。
少量のデータを扱う場合は、それほど重要ではありません。これらの場合、通常、言語の標準ライブラリが提供するものであれば何でも使用できます。
ただし、大量のデータを扱う場合、または何らかの理由でプログラムが高速であると主張する場合は、計算の複雑さを理解する必要があります。そうでない場合、問題をどのように解決する必要があるか、またはそれをどれだけ早く解決することができるかをどのように知るのですか?しかし、理論だけを理解しても、本当に優れたプログラマーになるには十分ではありません。非常に高速なコードを生成するには、マシンの動作方法(キャッシュ、メモリレイアウト、命令セット)、コンパイラーの動作(コンパイラーは最善を尽くしますが、完璧ではありません)も理解する必要があります。
要するに、複雑さを理解することは明らかにあなたをより優れたプログラマーにすると思う。
重要なアルゴリズムを開発している人がアルゴリズムの複雑さを理解していない場合、それは確かに問題です。アルゴリズムのユーザーは一般に、優れたパフォーマンス特性を持つ優れた実装品質に依存しています。複雑さはアルゴリズムのパフォーマンス特性の唯一の要因ではありませんが、重要な要因です。アルゴリズムの複雑さを理解していない人は、有用なパフォーマンス特性を持つアルゴリズムを開発する可能性が低くなります。
利用可能なアルゴリズムが良質であると仮定すると、アルゴリズムのユーザーにとってはそれほど問題ではありません。これは、重要で、明確に指定された標準ライブラリを持つ言語を使用する開発者に当てはまります-ニーズを満たすアルゴリズムを選択する方法を知る必要があるだけです。問題は、ライブラリ内で利用可能な何らかのタイプの複数のアルゴリズム(ソートなど)がある場合に発生します。これは、多くの場合、複雑さを選択するための基準の1つであるためです。複雑さを理解していない開発者は、手元のタスクに効果的なアルゴリズムを選択するための基礎を理解できません。
それから、(より良い説明のために)非アルゴリズム的な懸念に焦点を当てる開発者がいます。たとえば、直感的なユーザーインターフェイスの開発に焦点を当てることがあります。このような開発者は、アルゴリズムの複雑さを心配する必要はありませんが、やはり、高品質に開発されているライブラリまたは他のコードに依存する場合があります。
それは、作業しているデータの量ではなく、開発するプログラムの種類に依存します。
概念的な複雑さを知らないプログラマーを知らないプログラマーに電話しましょう。
noobishプログラマーができること:
noobishプログラマーはすべきではありません:
だから、テクノロジーを使いたいだけなら、noobishプログラマーは大丈夫です。ですから、新しいソリューションやカスタムテクノロジーなどの開発に関しては、初心者のプログラマーを雇わない方が良いでしょう。
ただし、会社が新しい技術を開発しない場合は、既に作成されたものを使用します。熟練した才能のあるプログラマーを雇うのは、才能の無駄です。同じことが当てはまります。新しいテクノロジーに取り組みたくなく、既に作成されたフレームワークを使用して顧客のアイデアをデザインやプログラムに入れるのが良い場合は、あなたが必要としないものを学ぶのは時間の無駄です。それがあなたの趣味であり、あなたが論理的な挑戦が好きなら。
私はここに答えを書くのを少しためらっていますが、他のいくつかのコメント(私のコメントの一部はチャットに移動しました)を細かく見つけたので、次のように表示します...
コンピューティングには多くのことに対する知識のレベル/程度があります(この用語では、コンピューターサイエンスと情報技術の大まかな統合を意味します)。計算の複雑さは確かに広大な分野であり(OptPとは何かを知っていますか?またはAbiteboul-Vianuの定理が言っていることを?)、また多くの深さを認めます:CS学位を持つほとんどの人は研究に入る専門家の証明を作成できません計算の複雑さの出版物。
私は、計算の複雑さの概念をいつ適用するかを知る状況(およびそれらを安全に無視できる状況を知る状況)と、Cでパフォーマンスに敏感なコードを実装するやや一般的なプラクティス(Javaの世界以外)とパフォーマンスに影響を受けない状況を敢えて比較しますPythonのものなど(余談ですが、これはジュリアの話では「標準的な妥協」と呼ばれています。)パフォーマンスについて考える必要がないことを知ることは、プログラミング時間を節約します。
そしてもう1つのポイントは、計算の複雑さを知っていても、プログラムの最適化が自動的にうまくいくわけではないということです。キャッシュの局所性、[場合によっては]パイプライン処理、そして最近ではパラレル/マルチコアプログラミングなど、アーキテクチャ関連のものをもっと理解する必要があります。後者には、独自の複雑性理論と実用的な考慮事項の両方があります。2013年のSOSP論文の後者の趣味「すべてのロックスキームには15分間の名声があります。すべてのターゲットアーキテクチャまたはワークロードで、他のどのロックスキームよりも常に優れていると考えられる9つのロックスキームはありません。したがって、ロックアルゴリズムは、ハードウェアプラットフォームと予想されるワークロードに基づいて選択する必要があります。」
big-Oがわからない場合は、学ぶ必要があります。難しくはなく、本当に便利です。検索と並べ替えから始めます。
私は、多くの回答とコメントがプロファイリングを推奨していることに気づきました。そして、それらはほとんど常にプロファイリングツールを使用することを意味します。
問題は、プロファイリングツールが高速化に必要なものを見つけるのにどれだけ効果的であるかという点で、マップ全体に存在することです。 ここで、プロファイラーが被る誤解をリストして説明しました。
その結果、プログラムがアカデミックなエクササイズよりも大きい場合、最高の自動プロファイラーでさえも公開できない眠れる巨人を含めることができます。 この投稿は、パフォーマンスの問題がプロファイラーからどのように隠れるかを示すいくつかの例を示しています。