時期尚早に最適化していますか?


9

私は現在、C ++のコンポーネントベースのアーキテクチャの設計段階にいます。

現在の設計には、次のような機能の使用法が含まれています。

  • std::vectorstd::shared_ptrコンポーネントを保持するsのs
  • std::dynamic_pointer_cast
  • std::unordered_map<std::string,[yada]>

コンポーネントは、グラフィックス、物理学、AI、オーディオなど、ゲームのようなソフトウェアに必要なさまざまなアイテムのデータとロジックを表します。

キャッシュミスがパフォーマンスに影響を与える可能性のある場所をすべて読んだので、いくつかのテストを実行しました。その結果、実際にアプリケーションの速度が低下する可能性があると思いました。

前述の言語機能をテストすることはできませんでしたが、多くの場合、これらの機能にはコストがかかる傾向があり、可能であれば回避する必要があると言われています。

アーキテクチャの設計段階にあり、これらは設計のコアに含まれるので、パフォーマンスがある場合、後で変更するのは非常に難しいので、今それらを回避する方法を見つける必要があります。問題?

それとも私は時期尚早の最適化をしているのですか?


3
パフォーマンスの問題に関係なく、後で変更するのが非常に困難になった設計に落ち着くのは非常に嫌です。可能であればそれを避けてください。柔軟で高速なデザインは数多くあります。
candied_orange

1
詳細を知らなくても、ほとんどの場合、この質問に対する答えは「YES !!」です。
Mawgはモニカを2016

2
@Mawg「...しかし、その重要な3%で機会を逃してはなりません。」これがデザインの中核なので、この3%に取り組んでいるかどうかはどうすればわかりますか。
Vaillancourt 2016

1
優れたポイント、アレクサンドル(+1)、そしてはい、私は引用の後半を知っています。 、the answer to this question is almost always a resounding "YES !!"。私はまだそれを最初に機能させて後で最適化する方が良いと感じていますが、YMMV、誰もが彼の意見を持っています、それらはすべて有効であり、OPだけが実際に彼自身の-主観的な-質問に答えることができます。
Mawgはモニカを2016

1
@AlexandreVaillancourt Knuthの論文を読み続けてください(PDF、引用は268とラベル付けされたページの右側から、PDFリーダーの8ページから)。「...彼は重要なコードを注意深く見るのが賢明でしょう。しかしそのコードが識別された後にのみ。プログラムのどの部分が本当に重要であるかについて事前に判断することは、測定ツールを使用してきたプログラマーは、直感的な推測が失敗することを経験しています。」(彼を強調)
8ビットツリー

回答:


26

タイトル以外は読まない:はい。

テキストを読んだ後:はい。マップや共有ポインターなどはキャッシュの点でうまく機能しないこと事実ですが、私が理解している限り、それらを使用したいものはボトルネックではなく、保持されません。データ構造に関係なく、キャッシュを効率的に使用します。

最も愚かな間違いを避けてソフトウェアを作成し、テストして、ボトルネックを見つけ、最適化します。

Fwiw:https ://xkcd.com/1691/


3
同意した。最初に正しく動作するようにしてください。動作に失敗する速さは問題ではありません。そして、最も効果的な最適化はコードの微調整を伴うのではなく、別のより効率的なアルゴリズムの発見を伴うことを常に覚えておいてください。
Todd Knarr

10
最適化は常に時期尚早であるため、最初の行は真実ではないことを指摘したいと思います。むしろ、最適化は、それが必要であることがわかっている場合にのみ時期尚早ではないためです。したがって、最適化が時期尚早であるかどうかについて質問しているという事実自体が最適化が必要かどうか確信が持てないため、最初の行は真実です。ふew。
イェルクWミッターク

@JörgWMittag:同意した。
steffen 2016

3

私はC ++に精通していませんが、一般的には異なります。

分離されたアルゴリズムを時期尚早に最適化する必要はありませんが、その場合は簡単に最適化できます。

ただし、目的の主要業績評価指標を達成するには、アプリケーションの全体的な設計を取得する必要があります。

たとえば、1秒あたり数百万のリクエストを処理するようにアプリケーションを設計する必要がある場合、アプリケーションを機能させるのではなく、アプリケーションを設計するときに、アプリケーションのスケーラビリティについて考慮する必要があります。


3

質問する必要がある場合は、はい。時期尚早の最適化とは、重大なパフォーマンス上の問題があると確信する前の最適化を意味します。


1

ECS?インターフェイス設計に影響を与える可能性があるため、設計のデータ指向の側面に多くの考慮を置き、さまざまな担当者をベンチマークするのは時期尚早ではない可能性があることを実際に示唆します。後者は後半に変更すると非常にコストがかかりますゲーム。また、ECSは多くの作業を必要とし、事前に考えます。そのため、その一部を利用して、設計レベルのパフォーマンスの悲しみが将来の心臓部にあることを考えれば、それより下に行かないようにする価値があると思います。全体の異常なエンジン。この部分は私をにらみつけます:

unordered_map<string,[yada]>

小さな文字列の最適化でも、別の可変サイズのコンテナー(unordered_maps)内に可変サイズのコンテナー(文字列)があります。あなたのテーブルが非常にまばらである場合には、小さな文字列の最適化は、ハッシュテーブルの各未使用のインデックスはまだ(SS最適化のためのより多くのメモリを使用することを意味するものであろうから、実際には、小さな文字列の最適化は、実際には、このような場合に役立つなどの有害となる可能性がありsizeof(string)ます非常に大きくする)ハッシュテーブルの合計メモリオーバーヘッドが、格納するものよりもコストがかかる可能性がある点まで(特に、位置コンポーネントのような単純なコンポーネントである場合)、巨大なストライドによってキャッシュミスが増えるハッシュテーブルのあるエントリから次のエントリに移動します。

文字列はコンポーネントIDのようなある種のキーであると想定しています。もしそうなら、これはすでに物事を劇的に安くします:

unordered_map<int,[yada]>

...たとえば、スクリプト作成者が使用できるユーザーフレンドリな名前を付けることができるという利点が必要な場合は、インターンされた文字列によって、ここで両方の長所を利用できます。

そうは言っても、文字列をかなり使用頻度の高いインデックスの範囲にマッピングできる場合は、次のようにできるでしょう。

vector<[yada]> // the index and key become one and the same

私がこの時期尚早とは思わない理由は、これもまた、インターフェースの設計に影響を与える可能性があるためです。DODの目的は、一回のIMOで想像できる最も効率的なデータ表現を考え出そうとすることではなく(通常、必要に応じて反復して達成する必要があります)、それを上手にインターフェイスを設計するのに十分なものと考えることです。設計変更をカスケードすることなくプロファイリングおよび最適化するための十分な余地を残したデータ。

単純な例として、これに対してすべてのコードを結合するビデオ処理ソフトウェア:

// Abstract pixel that could be concretely represented by
// RGB, BGR, RGBA, BGRA, 1-bit channels, 8-bit channels, 
// 16-bit channels, 32-bit channels, grayscale, monochrome, 
// etc. pixels.
class IPixel
{
public:
    virtual ~IPixel() {}
    ...
};

単一のピクセルレベルでの抽象化のアイデアはvptr画像レベルでの抽象化と比較して(それ自体がピクセル全体よりも多くのメモリを消費することが多い)ため、非常に非効率的です。多くの場合、数百万のピクセルを表します)。そのため、このような悪夢のようなシナリオに直面する必要がなく、理想的にはそれ以上にならないように、事前にデータ表現を十分に検討してください。ただし、ここでは、このようなことを事前に検討する価値があると思います。 ECSを取り巻く複雑なエンジン。ECS自体が、設計レベルでの変更を必要とする方法のボトルネックであることがわかります。

ECSキャッシュミスに関しては、私の意見では、開発者はしばしばECSキャッシュフレンドリーにするために努力しすぎています。完全に連続した方法ですべてのコンポーネントにアクセスしようとする人びとが小額の強打を生み出し始め、多くの場合、データをあちこちにコピーしてシャッフルすることを意味します。たとえば、アクセスする前にコンポーネントインデックスを基数でソートするだけで十分です。少なくともメモリ領域をキャッシュラインにロードしない方法でアクセスし、それを排除するためにロードします。同じキャッシュラインの別の部分にアクセスするためだけに、同じループで繰り返します。そして、ECSは、全体にわたって驚くべき効率を提供する必要はありません。これは、物理システムやレンダリングシステムと同じくらい、入力システムのメリットを享受するようなものではないので、「良い」を目指すことをお勧めします 全体的な効率性と、本当に必要な場所での「優れた」性能。そうは言っても、unordered_mapそして、これstringは避けるのに十分簡単です。

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