14

この質問を見てください:なぜC / C ++コンパイラはコンパイル時に配列のサイズを知る必要があるのですか?コンパイラの実装者は、今(10年前のC99標準の一部です)足を濡らして効率的な実装を提供する必要があったはずです。

しかし、それでも(回答から)コストがかかると考えられているようです。

これはどういうわけか私を驚かせます。

もちろん、パフォーマンスの点では静的オフセットの方が動的オフセットよりもはるかに優れていることを理解しています。1つの提案とは異なり、実際にはコンパイラに配列のヒープ割り当てを実行させることはありません。測定された;)]

しかし、私はまだ想定されるコストに驚いています:

  • 関数にVLAがない場合、私が見る限り、コストはかかりません。
  • 単一のVLAがある場合は、すべての変数の前または後に配置できるため、ほとんどのスタックフレームの静的オフセットを取得できます(または、私には思えますが、スタック管理に精通していません)。

もちろん、複数のVLAから問題が発生しますが、専用のVLAスタックが機能するかどうか疑問に思いました。これは、VLAがカウントとポインタ(したがって既知のサイズ)で表され、セカンダリスタックで使用される実際のメモリがこの目的でのみ使用されることを意味します(したがって、実際にはスタックも)。

【言い換え】

VLAはgcc/VC ++でどのように実装されていますか?

コストは本当に印象的ですか?

[言い換えを終了]

vector動的割り当てのコストが発生しないため(サイズ変更できないという犠牲を払って)、現在の実装でも、たとえば、を使用するよりも優れているように思われます。

編集:

ここには部分的な応答がありますが、VLAを従来のアレイと比較することは不公平に思えます。サイズを事前に知っていれば、VLAは必要ありません。同じ質問で、AndreyTは実装に関していくつかの指針を示しましたが、私が望むほど正確ではありません。

4

2 に答える 2

4

VLAはgcc/VC ++でどのように実装されていますか?

AFAIKVC++はVLAを実装していません。これはC++コンパイラであり、C89のみをサポートします(VLAなし、制限なし)。gccがVLAを実装する方法はわかりませんが、可能な限り最速の方法は、VLAへのポインターとそのサイズをスタックフレームの静的部分に格納することです。このようにして、一定サイズの配列のパフォーマンスでVLAの1つにアクセスできます(スタックがx86のように下向きに成長する場合は最後のVLAです(逆参照[スタックポインター+インデックス*要素サイズ+最後の一時プッシュのサイズ])、そして、最初のVLAが上向きに成長する場合(逆参照[スタックフレームポインター+スタックフレームからのオフセット+インデックス*要素サイズ]))。他のすべてのVLAは、スタックの静的部分からベースアドレスを取得するためにもう1つの間接参照が必要になります。

[編集:また、VLAを使用する場合、コンパイル時にスタックポインターからのすべてのオフセットを計算できるため、コンパイラーはスタックフレームベースポインターを省略できません。これは、そうでなければ冗長です。つまり、空きレジスタが1つ少なくなります。—編集終了]

コストは本当に印象的ですか?

あまり。さらに、あなたがそれを使わなければ、あなたはそれに対してお金を払わない。

[編集:おそらくもっと正しい答えは次のようになります:何と比較して?ヒープに割り当てられたベクトルと比較すると、アクセス時間は同じですが、割り当てと割り当て解除が速くなります。—編集終了]

于 2010-12-03T22:55:21.170 に答える
0

VC ++で実装する場合、コンパイラチームはのバリアントを使用すると思い_alloca(size)ます。そして、コストは、スタック上で8バイトを超えるアラインメントを持つ変数(など__m128)を使用するのと同等だと思います。コンパイラは元のスタックポインタをどこかに格納する必要があり、スタックを整列するには、整列されていないスタックを格納するための追加のレジスタが必要です。

したがって、オーバーヘッドは基本的に余分な間接参照であり(VLAのアドレスをどこかに格納する必要があります)、元のスタック範囲もどこかに格納するため、プレッシャーを記録します。

于 2010-12-03T23:40:07.400 に答える