なぜミクロのパフォーマンスと効率を気にする必要があるのですか?


71

C / C ++ページの多くの質問と回答、具体的または間接的にマイクロパフォーマンスの問題(間接関数と直接関数とインライン関数のオーバーヘッドなど)、またはO(N 2)vs O(N log N)アルゴリズムの使用100アイテムのリスト。

私は、問題がない限り、または問題があることがわかるまで、常にマイクロパフォーマンスを気にせず、マクロパフォーマンスにほとんど気を配らずに、コーディングしやすく、信頼性の高いコードを維持します。

私の質問は、なぜ多くのプログラマーがそんなに気にするのかということです。それはほとんどの開発者にとって本当に問題なのでしょうか、それについてあまり心配する必要がないほど幸運だったのでしょうか、それとも私は悪いプログラマーですか?


5
+1、一般的な質問です。
iammilind

+1良い質問です。2つのタグを追加しました。それについて気にしないでください。

2
私は2つの偉大な引用を取り上げます1)「時期尚早の最適化はすべての悪の根源です。」2)時間の80%がコードの20%に費やされます(80/20ルール)。
ジェームズKhoury

2
私のO(n * n)の例についていくつかの答えが出ていることに気付きました。100個のアイテムのリストを明示的に指定しましたが、O(nlogn)の方が優れていると主張しており、将来のリストが1000から100万になるとパフォーマンスの改善が明示されます。プログラマーは実際の現在の要件ではなく、将来の可能な要件にプログラミングしているため、このマイクロ最適化の強迫観念はありますか?(どこで聞いたことがありますか...)
mattnz

5
@James Donald Knuthからの完全な引用は、「私たちは小さな効率を忘れるべきであり、時間の約97%を言うべきです:早すぎる最適化はすべての悪の根源です」。このスレッドの残りの3%については、良い答えがいくつかあります。
StuperUser

回答:


14

実際には、パフォーマンスがその詳細レベルで管理する必要のある問題になることはめったにありません。大量のデータを保存および操作することがわかっている場合は状況を監視する価値がありますが、そうでなければ、物事をシンプルに保つのが正しいでしょう。

陥りやすい最も簡単なトラップの1つは、特にこのようなきめ細かな制御を行うCおよびC ++の場合、最適化が早すぎ、レベルが高すぎることです。一般に、ルールは次のとおりです。A)問題があることが判明するまで最適化しない、B)プロファイラーを使用して問題領域であると証明されていないものは最適化しない。

B)の結果は次のとおりです。プログラマーは、パフォーマンスのボトルネックがどこにあるのかを予測することで悪名高いが、それが得意であると考えています。プロファイラーを使用して、遅い部分を最適化するか、コードの1つのセクションが何度も呼び出されて問題が発生している場合はアルゴリズムを変更します。


6
別の方法:一度実行する初期化コードは一般に最適化を必要としないので、他の場所を見てください。
マイクデシモーネ

3
「1回」の頻度に依存します。実行しているとき./configure、私は、実行時間の75%までは、スクリプトを実行するプログラムで「初期化」のコードに費やされるかもしれないと言って、ベンチャーでしょう。25〜50%が動的リンクに費やされることさえあります。
R ..

12
ルールAはひどいルールです。システムのアーキテクチャはパフォーマンスに重要な役割を果たしますが、後でアーキテクチャがパフォーマンス要件をサポートできない場合は、基本的に台無しになります。したがって、細かい詳細を渡すことはできますが、最初はこれを完全に無視するのは間違いです。
edA-qa mort-ora-y

3
@ edA-qa:以前はそう思っていましたが、長年にわたって、パフォーマンスの問題が懸念される前に、多くのプロジェクトが苦労したり失敗したりしていました。パフォーマンスの問題が発生するたびに、修正は比較的低コストで、数日または数週間でした。開発中の修正を検出したのは、他の「バグ」ほどの心配ではありませんでした。ただし、他のリスク項目と同様に、プロジェクトの早い段階でパフォーマンスコーンを特定し、軽減する必要があります。
マッテンツ

5
OPはなぜこれほど多くの注意を払うのかを尋ねました、OPが誰かが「心配するな!」と言うのを聞くことにもっと興味がなければ、この応答が実際にどのように質問に答えたのかわかりません。
赤い汚れ

54

あなたのリストのすべてがマイクロ最適化であると思います。

100個のアイテムリストでO(n * n)対O(NlogN)アルゴリズムを使用する

私はそれを見なければならないと思います。確かに、そのリストは現在100アイテムであり、すべてが小さいn高速です。しかし、同じコードが数百万行のリストで再利用され、コードはまだ持っていることにすぐに賭けます合理的に動作します。

適切なアルゴリズムを選択することは、決して最適化ではありません。同じコードが2か月後または2年後に使用されるデータの種類を知ることはありません。プロファイラーのガイダンスを使用して簡単に適用できる「マイクロ最適化」とは異なり、アルゴリズムの変更には、多くの場合、新しいアルゴリズムを効果的に使用するための大幅な再設計が必要です。(たとえば、一部のアルゴリズムでは入力データが既にソートされている必要があるため、アプリケーションの重要な部分を変更して、データがソートされたままになるようにする必要があります)


36
「正しいアルゴリズムを選択することは決してマイクロ最適化ではありません」の+1

9
私も+1しましたが、データサイズが確実に小さい場合にbig-O-optimalアルゴリズムを選択すると、開発時間、プログラムサイズ、さらにはメモリ使用量に悪影響を与える可能性があることに注意してください。ポーカーハンドをソートする場合、クイックソート、スムーズソート、またはマージソートを本当に作成しますか?単純な挿入ソートから始めるか、ソートネットワークを使用します。
R ..

8
それは面白い。マイクロ最適化に関するスレッドでは、多くの解説者が回答をマイクロ最適化します。;)
確保

5
「同じコードが数百万行のリストに再利用されるとすぐに賭けるつもりです」:それは問題の領域に完全に依存しています。例:チェスアルゴリズムを記述している場合、ボードサイズが変わらないことを合理的に確信できます。自動運転車をプログラムする場合、車輪の数もそれほど速く増加ません。
ニキエ

3
「正しい」という言葉の性質を考えると、「正しいアルゴリズムを選択することは決してマイクロ最適化ではない」のは嫌だからです。しかし、あなたの含意は本当に「最速または最も効率的な」アルゴリズムであると思いますが、これには同意しません。実装に時間がかかり、そのセグメントの速度またはスペースがほとんど問題にならない場合、最も効率的なアルゴリズムを選択するのは間違った選択です。
ケーシーパットン

18

ずいぶん前、私の最初の仕事で、組み込みシステム用のコードを書きました。これらのシステムは8086マイクロプロセッサを使用し、メモリが限られていました。Intel Cコンパイラを使用しました。私が構築した1つのシステムは、構造の3次元配列にアクセスする必要がありました。本が私に言ったように私はそれを構築しました:3つの次元に対してmallocを呼び出し、次の次元に行を割り当て、そしてエンドノードにcallocを割り当てます。

それはかなり複雑でした(当時の私にとって)、カーブフィッティング、ANOVAプロセス制御、カイ2乗分析を行う必要がありました。これを行ったライブラリはありませんでした。すべてを書き、すべてを8086に合わせる必要がありました。

システムは犬のように走りました。迅速なプロファイリングの後、最大の問題の1つがアロケーターであることを発見しました。この問題を解決するために、私はmallocの呼び出しをすべて中止し、1つの大きなメモリブロックの独自のメモリ管理を行いました。


同じジョブの別のケースでは、顧客は統計的プロセス制御システムの応答時間について不平を言っていました。私の前のチームは、オペレーターが信号とスイッチをトリップするためにブール論理を使用できる「ソフトウェアPLC」システムを設計していました。彼らはそれを今日「ドメイン固有言語」と呼んでいる単純化された言語で書きました。思い出したように((A1 + B1) > 4) AND (C1 > C2)、それは次のように見えました。

元のデザインは、評価されるたびにその文字列を解析および解釈しました。わずかなプロセッサでは、これは多くの時間を消費し、プロセスコントローラーがプロセスの実行ほど速く更新できなかったことを意味しました。

私はそれをもう一度見て、実行時にそのロジックをアセンブリコードに変換できると判断しました。一度解析しから、実行するたびに、アプリは動的に生成された関数を呼び出しました。いくつかのウイルスが今日するように、私は推測します(しかし、私は知りません;本当に知りません)。その結果、パフォーマンスが100倍になり、顧客と上司は本当に幸せになりました。

新しいコードは、私がカスタムコンパイラを作成したため、メンテナンス性がほとんどありませんでした。しかし、パフォーマンスの利点はメンテナンスの欠点を上回りました。


最近では、XMLフライを動的に解析する必要があるシステムで作業していました。ファイルが大きくなると、かなり時間がかかります。これはパフォーマンスに非常に敏感でした。解析が遅すぎると、UIが完全に使用できなくなります。

これらの種類のものは常に登場します。


だから....メンテナンスしやすく、書きやすいコードが必要な場合があります。時には、迅速に実行されるコードが必要な場合があります。トレードオフは、各プロジェクトで行う必要があるエンジニアリング上の決定です。


9
すべての例で、その後最適化するコストは、最初から高速コードを記述するよりもそれほど高くありませんでした。そのため、最初に低速でシンプルなコードを記述し、次に必要な場所で最適化することで、すべてのコードでうまく機能しました。
CodesInChaos

6
@CodeInChaos:答えはそうではないと主張していません。OPの質問「なぜマイクロパフォーマンスと効率を気にしなければならないのか?」最適化前の問題は、他の回答者によって推測されただけです。
webbiedave

12

大きな画像を処理してすべてのピクセルを反復処理する場合、パフォーマンスの調整が重要になる場合があります。


2
+1-また、高周波ファイナンス、あらゆる種類のオーディオ/ビデオエンコーダー/デコーダー、シミュレーションとモデリング(ゲームなど)、CPUスケジューラーやメモリマネージャーなどのシステム全体のビットなど
Billy ONeal

3
CAN重要であるが、ISあなたはそれがそうであることが証明されてきた後にのみ重要あなたは問題があると考えるところであることを、それをプロファイリングしました。(ヒント:おそらくないでしょう。)
ちょうど私の正しい意見

2
@JUST MY正しい意見:実際には、画像処理の場合、データ処理は通常2番目に大きい時間の消費者です(I / Oは依然として最大です)。ただし、I / Oの最適化には、多くの珍しい/クレイジーなデザインと、仲間のプログラマーによるそれらの受け入れが必要であり、改善することがまったく不可能な場合もあります。ただし、処理部分は通常、恥ずかしいほど並列化可能であるため、簡単に得られる利点です。(一つの微調整は、ストレート教科書実装として別で見られるかもしれません...あなたはVirtualDubののレベルに達していない限り)
rwong

12

文化の背後にある理由について少し教えてください。

20歳よりも40歳に近く、成人期を経て生計を立ててきたあなたは、C ++が町で唯一のゲームであり、デスクトップアプリが標準であり、ハードウェアがまだあった時代になりました帯域幅/パフォーマンス機能の面でソフトウェアよりも大幅に遅れています。

  • 以前は、大規模な(> 2G)ファイルを読み取ることができるように、愚かなプログラミングトリックを行う必要がありました...
  • 以前は実行可能ファイルのサイズを心配していました...
  • 以前は、プログラムが消費しているメモリの量を心配していました...
  • アルゴリズムの時間とスペースのトレードオフの決定を定期的に行いました...
  • でも、バックエンドに、私たちは持っていたまともなノーを処理するために、何のためにCまたはC ++でCGIプログラムを書くこと。RPSの...これは数桁高速でした。
  • 以前は、delphi / c ++ / vb間のパフォーマンスのメリットについてテストを実行していました。

非常に少数の人々は、今日これらの事を心配する必要があります。

しかし、10年前には、ソフトウェアが56kbモデムを介してダウンロードされ、5年前のPCで実行されることを心配する必要がありました。1996年のくだらないPCの状態を覚えていますか?4GBのハードドライブ、200Mhzプロセッサ、および128MbのRAMの観点から考えてください...

そして、10年前のサーバー?デルの「次世代」サーバーの価格は2000ドルで、2(!)1 Ghzペンティアムプロセッサ、2 GbまたはRam、および20 Gbハードドライブが付属していました。

それは単に別の球技であり、10年の経験を持つすべての「シニア」エンジニア(あなたの質問に答える可能性が高い人)が、その環境で切る


1
さらに20年の経験は、最適化プロセスを何度も何度も繰り返した結果、書き込みマークを取得し、後で必要になることを避けることを意味します。同じ理由で、ハンマーを使用している間、親指を(あまり)叩かない。
Blrfl

1
ループ巻き戻し<shudder>
赤汚れ

5
そして今日、帯域幅、CPU、メモリは無制限だと思っていたすべての子供たちは、モバイルアプリケーションがうまく機能しないことに気付いています。
gbjbaanb

9

ここにはすでに10個の答えがあり、いくつかは本当に良いですが、これは私の個人的なペットの苦労だからです...

a)単純な解決策よりも時間がかかる早すぎる最適化b)単純な解決策ではサイズが半分、複雑さが半分になるコードを導入し、c)読みにくくすることは絶対に避けてください ただし、開発者がstd :: mapまたはstd :: vectorを使用するかどうかを選択し、早すぎる最適化よりも悪くないにしてもパフォーマンスが悪いという純粋な無知から間違ったコレクションを選択した場合。今日コードをわずかに変更し、読みやすさを維持し、同じ複雑さを保ちながら、より効率的にすることができたらどうしますか?それとも「時期尚早な最適化」と呼びますか?私は、多くの人々が何らかの方法でそれを考えさえしないだろうと思います。

変更がほとんど必要ない「マイクロ最適化」をアドバイスした人物になったとき、「早く最適化すべきではありません。それを機能させて、それを変更します」と言ったのと同じ応答を受け取りました。パフォーマンスの問題がある場合は後で」。修正するまでにいくつかのリリースが必要でした。はい、それはパフォーマンスの問題でした。

初期の最適化は良くないかもしれませんが、そのコードが何をしようとしているのかを理解してコードを書き、O(x)表記法が「最適化」であるという質問を単に無視しないと非常に有益だと思います。今すぐに書くことができるコードがたくさんあり、パフォーマンスについて少し考えれば、今後の問題の80%を回避できます。

また、多くのパフォーマンスの問題が環境内ですぐに発生することはありません。場合によっては、限界を押し広げる顧客がいるか、別の開発者がフレームワークの上に構築し、オブジェクトの数を10倍に増やすことを決めます。現在はパフォーマンスについてはある程度ですが、後で非常にコストのかかる再設計を避けることができます。また、ソフトウェアが公式にリリースされた後に問題が見つかった場合、簡単な修正でさえ適用するのに20倍の費用がかかります。

結論として、パフォーマンスを常に念頭に置くことは、良い習慣を身につけるのに役立ちます。これは、できるだけ簡潔で整理されたコードを書くのと同じくらい重要です。


+1:これは、Shrinkwrapソフトウェアと商用Webサイトを開発するために雇われた人々の雇用可能性要因の1つです。予防は、顧客の呪いよりも安価です。
-rwong

6

あなたが見ているものの多くは、単純なサンプリングエラーだと思います。人々が簡単な状況に対処しているとき、彼らはコードを書き、それは物事の終わりです。特に、最適化が必要であることが必ずしも明らかではない状況で、最適化が必要な場合など、比較的トリッキーなものを扱っているときに質問します。

そうは言っても、間違いなくいくつかの時期尚早な最適化が関係しています。正しくもそうでない場合も、CとC ++はパフォーマンスに定評があり、それはパフォーマンスを気にする人を引き付ける傾向があります。


1
+
1-

3
最適化の時期尚早な質問がここにたくさんあるのは確かです...多くの趣味のプログラマーがゲームを書くという考えから始めたという事実から来ていると思います。そして、ナンセンスな「最適化」本と初心者の頭の中に悪いアイデアを入れているゲーム開発に関連するウェブサイト。:-)
R ..

4
あなたはトリッキーなものを扱っているとき、多くの場合、トリッキーな問題から休憩を取ると、あなたが使用する必要があるかどうかを心配するあなたの時間を離れてフリッターしやすいと思われるi++++i
Carson63000

@ Carson63000:はい、サンプルを完全に歪める可能性があります。または、彼らが私のoperator ++コンパイルできない理由についての質問に答えるのに時間を費やします。
rwong

4

他のいくつかの回答では、組み込みシステムに言及していますが、これについて詳しく説明します

ローエンドプロセッサを搭載したデバイスはたくさんあります。たとえば、家のボイラーコントローラー、単純なポケット電卓、または現代の車の中の数十個のチップです。

お金を節約するために、これらには大量のフラッシュ(コードを保存するため)とRAMがあり、これらはPCやスマートフォン用のコードを書いただけの人には小さいように見えます。電力を節約するために、比較的低いクロックレートで動作する場合があります。

例を挙げると、STM32ファミリのマイクロコントローラは、24 MHz、16 KBフラッシュと4 KBのRAMから、最大120 MHz、1 MBフラッシュと128 KBのRAMまであります

これらのようなチップ用のコードを書くとき、もちろんコードを可能な限り効率的にすることを目指すなら、それは多くの時間を節約します。明らかに、時期尚早な最適化は悪い考えのままです。しかし、実践すれば、一般的な問題を迅速に、および/または最小限のリソースでどのように解決できるかを学び、それに応じてコードを作成できます。


1
私が自分で働いている分野である組み込みシステムについて考慮すべき良い点。それを念頭に置いて、長年の私の経験では、誤った最適化は常に時間の無駄です。ツールは、私たちを導くためにすることなく、我々はほとんど問題領域を見つけていない
ジェフ・

2

1は、時間の99%を引き起こしている問題ではないだろう1つの詳細な病理学的パフォーマンスの場合に実行されるとき、これらは、基本的に低レベルの言語であることボトルネックは、1が実際に直接、他のほとんどのとは異なり(問題を回避する機会を持っています言語); しかし、もちろん、最も効果的な方法はすぐにはわかりません。したがって、ここで尋ねられる奇妙な/興味深いマイクロ最適化の質問の半分。

残りの半分は、どれだけ金属に近づくことができるかを知りたがっている人から来ています。結局のところ、これらは本質的に低レベルの言語です...


+1:言語やプラットフォームに関係なく、「病理学的パフォーマンス」は世界中の誰にでも起こりうることを指摘する価値があります。テストおよび読み取り逆アセンブリのために低レベル言語で再実装する機能は、より多くの洞察を提供する可能性がありますが、常に実行可能なソリューションを提供するとは限りません。例:「アセンブリで実行できることはわかっていますが、部分信頼環境で実行する必要があります!」
rwong

2

CとC ++を扱う場合、パフォーマンスは常にホットなトピックです。どれだけ遠くまで行けばよいかについては、ASMのインライン化や、反復処理の高速化のためのポインター演算の使用など、いつでも夢中になります。しかし、最適化に非常に多くの時間を費やして、プログラム全体の開発に取り組むのが止まってしまうところがあります。

これらの問題に対処する場合、プログラマーのパフォーマンスとコードのパフォーマンスがあります。これらのどれに焦点を当てると、常に興味深い質問が表示されます。最後に、最も重要な質問は、ユーザーにとってどれほど目立つかです。ユーザーは、数百または数千の要素を持つ配列を作成するデータを操作しますか?この場合、物事を迅速に処理するためのコーディングでは、プログラムの標準操作が遅いとユーザーから不満が出る場合があります。

次に、少量のデータを処理するユーザーがいます。パフォーマンスを犠牲にして保守を容易にする高レベルの関数を使用している場合、ユーザーは、並べ替えやファイル操作などを行うことがそれほど目立たない、あちこちのいくつかのファイル。

これは、遭遇する問題のほんの一例です。その他の問題には、ターゲットユーザーのハードウェアが含まれます。組み込みシステムを扱う場合、ユーザーがラムのギグを備えたデュアルコアマシンを持っている場合、パフォーマンスについてさらに心配する必要があります。


うーん。高速な反復にはポインター演算を使用しません。インデックスベースの反復を使用する場合でも、ポインターベースの反復を使用する場合でも、ループごとの乗算および加算命令です。ただし、通常はインデックスベースの反復よりも明確なので、使用します。
ビリーONeal

ポインター演算はw / eより高速ではありません。

2

なぜプログラマーはそんなに気にしますか?頭を抱えている馬鹿げたアイデアがあります。たとえば、パフォーマンスの問題があると気づく前に解決し、推測するタイミングを理解しないなどです。

私の経験では、事前に考慮すべきパフォーマンスの問題があるため、注意が必要です。それらが何であるかを知るには経験が必要です。

とはいえ、私が使用する方法はあなたのものと似ていますが、同じではありません:

  1. 可能な限り単純な設計から始めます。特に、データ構造はできる限り正規化され、最小限である必要があります。避けられない冗長性がある限り、一貫性を保つ方法として通知を恥ずかしがるはずです。一時的な矛盾を許容し、定期的なプロセスで修復することをお勧めします。

  2. プログラムが開発中である場合には、定期的にパフォーマンスチューニングを行い、パフォーマンスの問題は静かに忍び寄るの方法を持っているので。私が使用方法があるランダムポーズ私はそれが最高だと思うので、。

ここに私が言っていることのブローバイブローの例があります。


1

正直に言うと、それはあなたの目的が何であるか、そしてあなたがプロとしてプログラミングしているのか、趣味としてプログラミングしているのかによって異なります。

今日、現代のコンピューターは本当に強力なマシンです。どのような基本的な操作を決定するかに関係なく、マイクロ最適化を試みているかどうかに関係なく、ジョブを非常に高速に実行できます。しかし、もちろん、何か他のこと(たとえば、物理学や化学などの分野のスーパーコンピューティング)をしている場合は、必要なだけ最適化することができます。

初期のMITプログラマーは素晴らしいものを作るために生まれたのではありません。彼らは、既存のアルゴリズムの簡素化と強化を開始しました。彼らの誇りは、2 + 2で既存のアルゴリズムよりも2秒で4を少なくすることでした(これは単なる例であり、アイデアは得られます)。彼らは、パフォーマンスのためにTI-83マシンで常に少ないパンチカードを使用しようとしました。

また、組み込みシステム用にプログラミングしている場合、マイクロパフォーマンスに注意する必要があります。別のデジタルクロックよりも5ナノ秒早く1秒刻みの遅いデジタルクロックを使用したくない場合。

最後に、もしあなたが趣味のプログラマであれば、たとえあなたのプログラムが高速であっても、細部を最適化することには確かに害はありません。それは必要ではありませんが、確かにあなたが取り組むことができ、より多くを学ぶ機会を取ることができます。あなたがソフトウェアの一部で専門的に作業している場合、それは非常に必要でない限り、その贅沢を取ることはできません。


1
趣味のプログラマーになることは、これとは何の関係もないと思います。あなたが専門的に何かをしていないからといって、必ずしもあなたが世界中でそれに費やす時間があるというわけではありません。さらに、ほとんどの愛好家は、ほとんどの真のプロが行うよりも、間違ったアルゴリズムを選択するなどの大きな間違いを犯します。さらに、専門家はおそらく、趣味よりもはるかに多くのデータを処理する製品に取り組んでおり(したがって、より高速でなければなりません)、アプリのパフォーマンスに顧客を満足させなければなりません。愛好家にはそのような制約はありません。
ビリーONeal

彼らはそうではありませんが、彼らは単に彼らがしたい場合に彼らに取り組むためのより多くの時間があります。

3
私は反対を主張します。私はプロとして何かに取り組むために1日8時間以上持っています。趣味のプロジェクトでは、1日あたり1時間か2時間かかります。
ビリーONeal

1

100項目リストでO(N2)対O(NlogN)アルゴリズムを使用します。

私は最近同様の状況にありました。アイテムの配列がありました。予想されるケースでは、リストに2つ(!)のアイテムがありました。最悪の場合でも、4つまたは8つ以上のアイテムは期待していません。

そのリストをソートする必要がありました。結果std::sortとして、ソートネットワーク(本質的には多数のネストされたif)に置き換えられ、実行時間の大部分が削減されました(数値は覚えていませんが、10〜20%程度でした)。これは、マイクロ最適化の大きな利点であり、コードは絶対にパフォーマンスが重要です。

もちろん、プロファイリングにのみこれを行いまし。しかし、要点は、C ++ほど不便で複雑​​な言語を使用する場合(オーバーロード解決のためのイライラするほど複雑なルールは言うまでもありません)、完全なメリットを享受したいということです。


1

累積エネルギー使用

これらの議論には常に欠けていると思う答えが1つあり、それが少し累積的なエネルギー使用量を悩ませます

確かに、高レベルのインタープリター言語でプログラムを作成し、間接的なレイヤーをいくつか使用してブラウザーで実行するか、ループに0.001秒ではなく0.01秒かかる場合は、大した問題ではないでしょう。誰も気付かない、つまり、個々のユーザーは気付かないでしょう。

しかし、何万人、場合によっては何百万人ものユーザーがコードを使用すると、その非効率性がさらに増大します。ツールがCPUを1日にたった10秒間スリープ状態にすることを防ぎ、100万人のユーザーがそれを使用する場合、非効率的なアルゴリズムは1日あたり140 kWh [1]余分に消費します。

私はこれが議論されることはめったになく、それは悲しいと思います。Firefoxのような人気のあるフレームワークや派手なインタラクティブなWebアプリケーションでは、この数値がはるかに悪いと強く疑っており、調査することは興味深いでしょう。


[1]私はちょうどそれを作りました、1000万秒×50ワット。正確な数値は多くのことに依存します。


1
魔法の言葉「モバイル」に言及することから始めましょう。デスクトッププラットフォームで実行する場合、1秒間に60回フレームを描画するためにCPU時間の1/100秒かかるアプリケーションは「十分に高速」です。パフォーマンスを10倍向上させると、ユーザーに影響はありません。ただし、モバイルプラットフォームでは、CPU使用率が90%で実行されるアプリケーションは、10%で実行されるよりもはるかに高速にバッテリーを消費します。
-supercat

1

強力なパフォーマンスが要求される線形時間よりも優れていないアルゴリズムがある場合があります。

例は、すべてのピクセルをループせずに画像/フレームを基本的な例として明るくすることができないビデオ処理です(まあ、最終的に画像タイルに下る子によって継承されたプロパティを示す何らかの階層構造でできると思います葉ノードの場合は、すべてのピクセルをレンダラーにループするより高いコストを延期します。コードは、最も最適化された画像フィルターよりも維持するのが難しいでしょう。

私の分野ではそのようなケースがたくさんあります。私は、あらゆる種類の洗練されたデータ構造またはアルゴリズムの恩恵を受けるものよりも、すべてに触れたり、すべてを読んだりする必要がある線形複雑ループを実行する傾向があります。すべてに触れる必要がある場合にスキップできる作業はありません。そのため、その時点で線形の複雑さを避けられない場合、反復ごとに行われる作業をますます安くする必要があります。

したがって、私の場合、最も重要で一般的な最適化は、多くの場合、データ表現とメモリレイアウト、マルチスレッド、SIMDです(通常、この順序でデータ表現が最も重要であり、後者の2つを実行する能力に影響します)。木、ハッシュテーブル、並べ替えアルゴリズム、およびそのようなものによって解決されるような多くの問題に直面していません。私の毎日のコードは、「それぞれに対して、何かをする」ということです。

もちろん、最適化が必要な場合(さらに重要なことは、必要でない場合)、マイクロまたはアルゴリズムについて話すことは別のケースです。しかし、私の特定のケースでは、クリティカルな実行パスに最適化が必要な場合、10x +の速度向上は、マルチスレッド、SIMD、メモリレイアウトとアクセスパターンの再配置などのマイクロレベルの最適化によって達成され、参照の局所性が向上します。たとえば、バブルソートをイントロソートまたは基数ソートに置き換えたり、BVHを使用した2次複雑性の衝突検出を、ホット/コールドフィールドスプリットの恩恵を受けるホットスポットを見つけるほど頻繁に置き換えることはあまりありません。

私の場合、私の分野はパフォーマンスが非常に重要であるため(レイトレーシング、物理エンジンなど)、イメージをレンダリングするのに10時間かかる遅いが完全に正しいレイトレーサーは、役に立たないか、完全にインタラクティブであるが高速のものよりも多くの場合、水密光線/トライ交差の欠如によりどこでも漏れる光線で最もgliい画像を出力します。速度は間違いなくそのようなソフトウェアの主要な品質指標であり、おそらくある点までの正確さよりもはるかに優れています(「正確さ」は、クラッシュしない限り、すべてが近似であるため、レイトレーシングでは曖昧な考えであるため)。その場合、効率について事前に考えなければ、より効率的な設計を処理するために、最も高価な設計レベルで実際にコードを変更する必要があります。だから私がしなければ

ゲームも私のものに似た分野です。ゲームがスライドショーのように1秒あたり1フレームで実行される場合、ゲームロジックがどれだけ正しいか、コードベースがどれだけ保守可能かつ見事に設計されているかは関係ありません。特定の分野では、速度の不足が実際にアプリケーションをユーザーにとって役に立たないものにする可能性があります。ゲームとは異なり、レイトレーシングなどの領域には「十分な」メトリックはありません。ユーザーは常により高速を求めており、産業競争は主に高速なソリューションを求めています。ゲームがパストレーサーを使用するリアルタイムになるまで、これで十分ではありません。そして、アーティストは数十億のポリゴンをロードし、30 + FPSで数十億のパーティクル間で自己衝突を伴うパーティクルシミュレーションを行うことを望むかもしれないので、おそらくVFXにはまだ十分ではありません。

快適であれば、パフォーマンスに関わらず、スクリプト言語(Lua)でコードの約90%を記述します。しかし、実際には数百から数十億のものをループする必要がある異常に大量のコードがあり、数百から数十億のものをループしているとき、あなたは素朴なシングルスレッドのコードの壮大な違いに気づき始めます繰り返しごとにキャッシュミスを引き起こします。たとえば、ベクトル化されたコードは、無関係なデータがキャッシュラインにロードされない連続したブロックにアクセスして並行して実行されます。


0

あなたが言及したように、これらの問題によって実際に引き起こされるいくつかの問題を説明する前に、マイクロパフォーマンスの問題を気にすることは価値がありません


0

一般的にこの質問に答えることは本当に不可能です。現在構築されているほとんどのソフトウェアは、内部WebサイトとLOBアプリケーションであり、そのようなプログラミングでは、あなたの推論は非常に正しいです。一方、デバイスドライバーやゲームエンジンのようなものを書いている場合、最適化は「時期尚早」ではありません。ハードウェアの制約が異なる非常に異なるシステムでソフトウェアが実行される可能性があります。その場合、パフォーマンスを考慮して設計し、最適でないアルゴリズムを選択しないようにしてください。


まさに私が言いたかったこと。すべてのソフトウェアにはアプリケーションドメインがあり、それ以外では最適に動作することを期待すべきではありません。この意味で、時期尚早な最適化は、見当違いの完全主義の例です。
K.ステフ

0

パフォーマンスを非常に重視するプログラマーの問題は、彼の人生の中で、時には非常に緊急にマイクロパフォーマンスのコードを書く必要があり、彼は学んだ、学んだ、学んだ、そして最終的に知っていたと思う多くのこととトリック。

そして今では忘れることは難しく、事前の測定なしでは、彼は心配する必要がないことを示しており、高速コードを使用して安全な側にいます。

深い知識、スキル、いくつかのトリックを示し、学んだことを再利用することは常に素晴らしいことです。それはあなたに価値を感じさせ、時間は学習に費やし、価値があると感じさせます。

ライブで時々、プレフィックスの増分が速いことを学びました...

for (int i = 0; i < MAX; ++i)

...後置増分より:

for (int i = 0; i < MAX; i++)

ここで、MAXが低い場合は重要ではなく、ループ内に実際の作業があれば、それも重要ではありません。しかし、今日のコンパイラが独自にコードを最適化しても、後置バージョンを使用する理由はありません。

おそらく、パフォーマンスを求める人は、オプションの大きな海でガイドラインを作成するために、「作業コードと読み取り可能なコード」のような「作業コード」を書くことに加えて、追加の目標が必要です。


0

私はそれについてあまり心配する必要がないほど幸運だったのですか、それとも私は悪いプログラマーですか?

要件を気にしますか?パフォーマンスが要件でない場合は、心配する必要はありません。それにかなりの時間を費やすことは、あなたの雇用主に対する不利益です。

ある程度のパフォーマンスは常に要件です。あなたがそれについて考えずにそれを打つことができるなら、あなたはそれについて考えないことを正当化されます。

個人的には、テストに合格するまでに時間がかかると、ほとんどの場合、パフォーマンスに左右されます。一連のテストがパスする間、5分間待つのが待ちきれません。しかし、それは通常、テストをいじることによって解決されます。

私の質問は、なぜ多くのプログラマーがそんなに気にするのかということです。それは本当にほとんどの開発者にとって問題ですか、

気にかけていることを正当化する多くのプログラマーがいます。そうでない多くの人がいます。そうでない人について話しましょう。

プログラマーが学校で最初に学ぶことの1つは、物事を実際に機能させる方法の後、大きなO表記法です。それらの多くはレッスンを適切に学習し、nによって劇的に影響を受けるものに適切に焦点を合わせます。他の人は、数学を取得せず、一度動作する必要があるという教訓を取り除くだけです。さらに悪いことに、これらの学生の何人かは、コードを機能させ、高速に機能させること以外に、コードで何をすることが重要であるかについて他のことをまったく学ばない。見落とされた教訓:読みやすく、うまく設計し、理由もなく遊んではいけません。

Knuthは正しかった。時期尚早の最適化がすべての悪の根源だ。しかし、それが機能したら、次のステップは何ですか?速いよね?番号!次のステップは読みやすいです。読み取り可能は、最初、次、中間、最後のステップです。不要なパフォーマンスの最適化を行う人の多くは、バスの下で読みやすくしています。

一部の人は、コードがどれだけ読めないかというスリルを味わうことさえあります。彼らは、他の人が作成したコードを理解するのに苦労しなければならなかったので、今は投資回収の番です。

私はこれをしていたので、これを知っています。構造が完全に読み取り可能な5行を判読不能な1行のブール式にリファクタリングしたことがあります。私は望んでいた賞賛を得ることができませんでした。

コードが読みやすいままであれば、後で高速化するのは簡単です。それが、Knuthが「不要」ではなく「時期尚早」を強調している理由です。確かに、速いほど優れているからです。しかし、良いのは、あなたがそれのために何を犠牲にするかによってのみ良くなります。そのため、実際に必要なパフォーマンスがわかるまで待ってから、犠牲を払ってください。読みにくくなると、消極的になります。

可読性を超えて、ソフトウェア設計の全世界があります。このサイトの内容。設計に関して何をすべきかわからない人もいます。だから彼らはデザインに感銘を与えられないので、彼らは判読できない混乱を作ります。誰もコードを修正しないので、適切なコードである必要があります。

一部の人にとって、パフォーマンスとは、やりたいことをすべて実行するための言い訳です。プログラマーには多くの力と自律性があります。それらに信頼が置かれています。信頼を濫用しないでください。

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