変数のアクセス速度について


やよい  2011-03-04 18:14:37  No: 72407

失礼します。

外部変数参照する(externで外部リンケージ)場合、一般論として自前のと較べたら、遅い可能性はありますか。

例えば、変数はコードと同じ*.c(*.cpp)内に存在すれば、フレームポインターやセグメントアドレスの付加が要らず済ませるに対して、外部変数の場合そう限らなくて、アドレスが長くなるとか、、、
↑理論的に成り立つのでしょうか

ご存じの方宜しくお願いします


仲澤@失業者  2011-03-04 19:59:04  No: 72408

環境や条件が記載されていませんので、32bit Windowsと仮定すると、
「一般にはそういうことは無い」
と言っておきます。アロケーションされていない変数はスタック上に
存在し、そのアクセス方法は単純です。externは、翻訳単位では
存在しない変数を、あるものとしてコンパイルし、リンク時に
アドレス解決する。というC言語上の手順であって、リンク後の
実行ファイルの中身では、externという意味は失われて、
グローバル変数は全て伸べ単で並んでます。

ただし、CPUにキャッシュがある場合(ほとんどのものがそうですが)
キャッシュにヒットしている場合と、そうでない場合はスピードが
全然違います。実行ファイルの全体、またその全データごとキャッシュに
乗っていると、最も高速になります。

また、レジスタにエイリアスを保持しておけない様に
volatile宣言された変数のアクセスは時間がかかります。


tetrapod  2011-03-04 20:07:08  No: 72409

日本語がわかりにくい・・・質問として致命的だ。要書き直し。
何と何を比較している/比較したいのか読み取れない。
以下勝手に俺解釈で続けるものとする。

ここは Visual C++ が主なので、プラットフォームは Windows 、 CPU も x86/x64 とする。
すると、
・静的変数か自動変数かで速度は大きく違う
・静的変数が内部結合 (internal linkage) か 外部結合 (external linkage) かどうかは無関係

自動変数はレジスタになることもあるので静的変数と単純比較できない。
一般的に自動変数より高速な静的変数というものは存在しない。

静的変数のアクセスはメモリアクセスになる。
メモリアクセスの速度はキャッシュのヒット率だけにほぼ依存する。
L1 キャッシュ=CPU ALU の速度、に対して
RAM = CPU ALU に比べて10倍から100倍遅い。
ページフォルトなど発生したら数億〜数兆倍の時間がかかる。
なので、巨大静的変数があってキャッシュに乗らない・・・というときに
同一ソース/他ソースで速度が違うことはあってもおかしくない。

今まさに実行中のコードは必ず L1 キャッシュに乗るので
アドレシングによる命令語長の違いなどはあっても影響度小

x86/x64 以外ではまた話は違うので当該 CPU のマニュアルを参照。


やよい  2011-03-04 20:43:54  No: 72410

みなさん丁寧なご解説本当にありがとうございます。
説明不足処が多かった事にお詫び申し上げます。

開発環境はwindows x86, 64bit+MS VC++です。

*****************************************************
今まさに実行中のコードは必ず L1 キャッシュに乗るので
アドレシングによる命令語長の違いなどはあっても影響度小
*****************************************************

以前から変数の実体がコードと同じ*.c (*.cpp)に存在すれば、
アドレスのセグメント部分が省略できるので、変数アクセススピードがその分速くなるという記憶ありますが、それはウソでしょうか。

申し訳ございませんが、これだけ再度ご確認させていただきます。


tetrapod  2011-03-04 21:49:23  No: 72411

えっと、少なくとも自分でコンパイル後バイナリは確認したの?
hoge.cpp から hoge.cod ファイルは出力してみたの?
x86/x64 アセンブラは読めるわけ?

セグメントプリフィックスが生成されるって 16bit 時代の話だと思うが。
LARGE モデルや HUGE モデルとかあった頃。 MS-DOS/Win3.0 の話。
いまどきの 32bit/64bit では FLAT メモリモデルを使うので
(少なくとも Ring 3 で動くアプリケーションプログラムでは)
セグメントプリフィックスバイトは生成されないよ。


仲澤@失業者  2011-03-04 22:22:54  No: 72412

>以前から変数の実体がコードと同じ*.c (*.cpp)に存在すれば、
>アドレスのセグメント部分が省略できるので、変数アクセススピードがその分速くなるという記憶ありますが、それはウソでしょうか。

そういう約束を、コンパイラとリンカがしてくれているという話は
聞いたことはないですねぇ。
16bit Windowsのころは、nearポインタ(=16bitアドレス)が使えたので、
明示的に、また、正しく実装すればやや早かったかもしれませんが(vv;)。

もちろんDOSやCPMの頃のCOMモデル(単一セグメント<64K)モデルのほうが
EXEモデルより実行が早いとか言うのはありましたけどね。
もう、そんな話を覚えている人などほとんど生息していませんが・・・。


やよい  2011-03-05 04:56:47  No: 72413

みなさん、本当にありがとうございました!

> EXEモデルより実行が早いとか言うのはありましたけどね。
> もう、そんな話を覚えている人などほとんど生息していませんが・・・。

普段「化石」とよく言われました!
実証されましたね ^<^;

また宜しくお願い申し上げます


ロマ  2011-03-07 02:06:42  No: 72414

16bitAppをPentiumで動かすと、DSやESの切り替え時に
ものすごくコストがかかったと記憶しています。

32bitだと、関数の記述順やリンク順で計算速度が変わったり、
計算前に大きな配列をnewしdeleteすると計算が早くなったこともあり、
もう、わけわからんです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加