私のプログラム コードには、1 バイトまたは 2 から約 16 までのさまざまなかなり小さなオブジェクトがあります。たとえば、Vector2 (2 * T)、Vector3 (3 * T)、Vector4 (4 * T)、ColourI32 (4)、LightValue16 (2 )、タイル (2) など (括弧内のバイト サイズ)。
プロファイリング(サンプルベース)を行っていたため、予想よりも遅い関数が発生しました。
//4 bits per channel natural light and artificial RGB
class LightValue16
{
...
explicit LightValue16(uint16_t value);
LightValue16(const LightValueF &);
LightValue16(int r, int g, int b, int natural);
int natural()const;
void natural(int v);
int artificialRed()const;
...
uint16_t data;
};
...
LightValue16 World::getLight(const Vector3I &pos)
{ ... }
この関数はいくつかの計算を行い、いくつかの配列を介して値を検索します。世界の人口の多い部分の上にいくつかのデフォルト値があります。コンテンツはきれいにインライン化されており、逆アセンブルを見ると、約 100 の命令が含まれているように見えます。ただし、1 つのことが際立っていました。すべてのリターン サイトで、次のように実装されていました。
mov eax, dword pyt [ebp + 8]
mov cx, word ptr[ecx + edx * 2] ; or say mov ecx, Fh
mov word ptr [eax], cx
pop ebp
ret 10h
x64 の場合、ほとんど同じことがわかりました。私は GCC ビルドをチェックしませんでしたが、ほとんど同じことをしていると思います。
少し実験して、uint16_t 戻り型を使用して見つけました。実際には、World::getLight 関数がインライン化され (ほぼ同じコア 80 命令のように見え、条件/ループが異なるチートはありません)、調査していた外部関数の合計 CPU 使用率が 16.87 から上昇しました。 % to 14.04% ケースバイケースでそれを行うことはできますが (強制的にインラインのものを試すことに加えて)、最初からこのようなパフォーマンスの問題を回避する実用的な方法はありますか? おそらく、コード全体で数 % 速くなるでしょうか?
私が今考えることができる最善の方法は、そのような場合 (< 4 またはおそらく 8 バイト オブジェクト) でプリミティブ型を使用し、現在のメンバーのものをすべて非メンバー関数に移動することです。名前空間だけで、C で行われるようになります。 .
これについて考えると、「t foo(float x、float y、float z)」よりも「t foo(const Vector3F &p)」のようなものを使用するコストもあると思いますか? もしそうなら、 const& を広範囲に使用するプログラムで、合計すると大きな違いになるでしょうか?