ゼロを置く場所を知る必要があります





最適化には、複雑なデータ構造と数千行のコードが必要です。 その他の場合、生産性の大幅な向上により最小限の変更が行われます。ゼロを設定するだけでよい場合もあります。 これは、ハンマーで打つ適切な場所を知っており、クライアントに請求するスキッパーに関する古い話のようなものです:バルブへの打撃に対して0.50ドル、打つ場所を知るために999.50ドル。



私は個人的にいくつかのパフォーマンスエラーに遭遇しましたが、1つのゼロを入力することで修正されました。この記事では2つのストーリーを共有したいと思います。



測定の重要性



オリジナルのXboxの時代、私は多くのゲームの最適化を支援しました。 そのうちの1つで、プロファイラーは行列変換関数を指しており、CPU時間の7%を消費しました。これはチャートで最大の跳躍です。 そのため、この機能の最適化に熱心に取り組みました。



私がこれをやろうとしたのは初めてではなかったことがわかります。 この関数は既にアセンブラーで書き直されています。 アセンブリ言語のいくつかの潜在的な改善を発見し、その効果を測定しようとしました。 これは重要なステップです。それ以外の場合は、「最適化」を行うのは簡単で、何も変更したり、状況を悪化させたりすることはありません。



しかし、測定は困難でした。 私はゲームを開始し、並列プロファイリングで少し遊んだ後、プロファイルを調査しました。コードは速くなりましたか。 若干の改善があったようですが、確かに言うことは不可能でした。



そこで私は科学的方法を適用しました。 彼は、パフォーマンスの違いを正確に測定するために、古いバージョンと新しいバージョンのコードを管理するテストのコレクションを書きました。 これにはそれほど時間はかかりませんでした。予想どおり、新しいコードは古いコードよりも約10%高速でした。



しかし、10%の加速はナンセンスであることが判明しました。



テストコードの内部でゲームの約10倍の速度で実行されたことはさらに興味深いです。 これはエキサイティングな発見でした。



結果を確認した後、私はしばらくの間空を調べましたが、それから私は夜明けしました。



キャッシングの役割



ゲーム開発者にフルコントロールと最大のパフォーマンスを提供するために、ゲームコンソールではさまざまな属性でメモリを割り当てることができます。 特に、元のXboxでは、キャッシュ不可能なメモリを割り当てることができます。 このタイプのメモリ(実際には、ページテーブル内のタグのタイプ)は、GPUにデータを書き込むときに役立ちます。 メモリはキャッシュされていないため、書き込みは、「通常の」マッピングによる遅延やキャッシュの汚染なしに、ほぼ即座にRAMに送られます。



したがって、非キャッシュメモリは重要な最適化ですが、慎重に使用する必要があります。 特に、ゲームがキャッシュされていないメモリから読み取ろうとしないことが非常に重要です。そうしないと、ゲームのパフォーマンスが著しく低下します。 元のXboxの比較的低速の733 MHz CPUでも、十分な読み取りパフォーマンスを提供するために独自のキャッシュが必要です。



今、何が起こっているのかが明らかになります。 どうやら、この機能では、データはキャッシュされていないメモリに割り当てられるため、パフォーマンスが低下します。 小規模なテストによりこの仮説が確認されたため、問題を修正する時が来ました。 メモリが割り当てられている行を見つけ、フラグ値をダブルクリックして、ゼロを指していました。



プロセッサー時間の約7%の代わりに、関数は約0.7%を消費し始め、問題ではなくなりました。



週の終わりには、私のレポートは次のようになりました。「39,999時間の研究、0.001時間のプログラミングは大成功です!」



開発者は通常、キャッシュされていないメモリを誤って割り当てることを心配する必要はありません。ほとんどのオペレーティングシステムでは、このオプションは標準の方法を使用するユーザー空間では使用できません。 ただし、キャッシュされていないメモリがプログラムの速度を低下させる可能性がある場合は、 VirtualAllocの PAGE_NOCACHEまたはPAGE_WRITECOMBINEフラグを試してください。



0 GiBは4 GiBよりも優れています



別の話をしたいです。 それは私が見つけたバグについてであり、他の誰かがそれを修正しました。 数年前、ラップトップのディスクキャッシュが頻繁にクリアされることに気付きました。 4 GiBマイルストーンに到達するとこれが起こることを追跡し、最終的に、新しいバックアップHDDのドライバーは、不明なセクターサイズを指すときにSectorSizeを0xFFFFFFFF(または-1)に設定することがわかりました。 Windowsカーネルはこの値を4 GiBとして解釈し、対応するメモリブロックを割り当てて問題を引き起こしました。



Western Digitalには連絡先はありませんが、定数0xFFFFFFFF(または-1)をゼロに置き換えることにより、このエラーを修正したと安全に想定できます。 1人のキャラクターが入力しました-そして深刻なパフォーマンスの問題を解決しました。



(この調査の詳細については、 「Windowsの速度低下:探索と識別」の記事を参照してください)



観察





#defineのコメントを外したり、その他の些細な変更を行って、コードを最適化しました。 そのようなストーリーがある場合はコメント欄で教えてください。



All Articles