質問

ベクトル/マトリックスライブラリを作成しています。 (GCC、アームネオン、iPhone)

typedef struct{ float v[4]; } Vector;
typedef struct{ Vector v[4]; } Matrix;

structデータをポインターとして渡して、呼び出し関数の際にデータのコピーからパフォーマンスが低下しないようにしました。だから私は最初はこのような機能を設計しました:

void makeTranslation(const Vector* factor, Matrix* restrict result);

しかし、関数がインラインである場合、パフォーマンスのポインターとして値を渡す理由はありますか?これらの変数もコピーされていますか?登録とキャッシュはどうですか?私はこのような機能を再設計しようとしました:

inline Matrix makeTranslation(const Vector factor) __attribute__ ((always_inline));

各ケースのコストを呼び出すことについてどう思いますか?

  • 提案を反映するために、2番目の署名に「const」を追加しました。
役に立ちましたか?

解決

関数がインラインである場合、通常、変数のコピーが呼び出しに直接関係していません。変数は引き続き移動し、実行の通常の部分としてスタックに置かれますが、関数呼び出しの直接的な結果としてはありません。 (レジスタが不足している場合、一部の値はスタックなどに置かれる可能性があります...しかし、必要な場合のみ)。スタックフレーム、これ以上無条件のジャンプはなく、プッシュ/ポップパラメーターはもうありません。)

あなたがあなたに頼ることができるなら always_inline 属性 いつも 関数をインラインで、ポインターでベクトルを渡さないでください(変更されていない場合)。この理由は、ポインターでそれを渡すにはベクトルのアドレスを取得する必要があるためです。つまり、コンパイラがアドレスを持っていることを確認する必要があり、したがってCPUレジスタにのみ存在できないことを意味します。これにより、必要でない場合に物事が遅くなり、コンパイラが住所が必要でないことを確認できないため、コンパイラが常にアドレスを持っていることを確認すると、物事を遅くすることができます。

パスバイポインターのため、このコードには常にオブジェクトのアドレスを取得するための命令があり、少なくとも1つの控除をメンバーの価値を得ることができます。ご価値がある場合、これはまだ発生する可能性がありますが、コンパイラはそのすべてを最適化できる可能性があります。

インラインの過剰使用により、コンパイラバイナリコードのサイズが大幅に増加する可能性があることを忘れないでください。特定の場合、大規模なコードセグメントを持つ(インライン関数の結果として)、より多くの指示キャッシュミスを引き起こす可能性があります。小型L1キャッシュに収まるには大きすぎます。これは、これらのプロセッサが通常小さなキャッシュを持っているため、埋め込まれたプロセッサ(iPhoneなど)で特に重要です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top