07/04/29 09:54:14
コンパイラ性能、コンパイルオプション、コードの最適化などについて語りましょう。
主に速度面の最適化を中心としますが、サイズなどの最適化もどうぞ。
なお、OS、CPU、コンパイラなどは限定しません
前スレ
C、C++の最適化について語るスレ
スレリンク(tech板)
2:デフォルトの名無しさん
07/04/29 12:32:25
2げtt
3:デフォルトの名無しさん
07/04/29 15:13:32
ポインタ使ったほうが速いの?
4:デフォルトの名無しさん
07/04/29 15:18:14
コンテナにオブジェクト詰めるときは
newしてそのポインタを詰めるとめがっさ軽くなる
5:デフォルトの名無しさん
07/04/29 15:36:28
>>3-4
オブジェクトのコピーがボトルネックになってる場合に限るけどな。
6:デフォルトの名無しさん
07/05/01 17:49:32
GPOを行う場合、1000回計算を行うループがあったとして、10回程度ループを回して計測して、最適化することはできないでしょうか?
一旦プログラムのすべてを実行しなければならないとしたら、毎回実行条件の違う
科学計算などではどのように最適化すればよいのでしょうか?
7:デフォルトの名無しさん
07/05/01 22:49:32
それは分岐予測というカタチでハードウェアが実行している。
コンパイラはそれが機能しやすいようにする。
8:デフォルトの名無しさん
07/05/02 02:20:57
ダンゴさんに声かけたか?
9:デフォルトの名無しさん
07/05/02 02:46:05
GPO? PGO?
10:・∀・)っ-○◎●
07/05/03 03:46:08
11:デフォルトの名無しさん
07/05/03 14:12:12
ダンゴは糞だからイラネ
12:デフォルトの名無しさん
07/05/03 14:48:47
>>11
団子ちゃんが馬鹿にするな!
13:デフォルトの名無しさん
07/05/03 16:02:50
が?
14:・∀・)っ-○◎●
07/05/03 16:06:59
がががーが・がーがが
15:デフォルトの名無しさん
07/05/03 18:16:38
そりゃぁ、自分の基準にそって馬鹿だと思えば馬鹿にもするだろうよ。
団子じゃなくたってね。
16:デフォルトの名無しさん
07/05/03 18:30:39
int型の配列を特定の数値で埋めたいのですが、forループで一つ一つ回していく以外に
何か高速な方法はありませんか?
17:デフォルトの名無しさん
07/05/03 18:35:44
スレ違いの気がするが
・初期化
・memset
18:デフォルトの名無しさん
07/05/03 18:37:15
>>16
SSE2の使えるCPU用でいいなら、真っ当なコンパイラに適当なオプションを指定すれば、
勝手にベクタ化してくれる。
但し、極真っ当にループを書くこと。
19:・∀・)っ-○◎●
07/05/03 18:40:24
memset使えば、コンパイラによっては最適化でより高速な命令に置き換えてくれることもある。
たとえばx86なら要素数4の倍数個で16バイトアラインされてれば
for (i = 0; i < ARRAY_SIZE; i++) {
a[i] = foo;
}
↓
__m128i xfoo = _mm_set1_epi32(foo);
for (i = 0; i < ARRAY_SIZE; i+=4) {
mm_store_si128(&a[i], xfoo);
}
みたいな明示的ベクトル化は可能。
20:デフォルトの名無しさん
07/05/03 19:28:44
ビット演算についての質問です。
やりたいことは、最大値511 (2^9 - 1) で負の可能性がある
あるint型の値の値域を 0~255 に絞りたいのです。
つまり、
x = (x <= 0 ? 0 : (x >= 255 ? 255 : x));
ですが、これを出来るだけ速くしたいのです。
(ちなみに、最終的に行いたいことはアドレス計算です)
一応自分なりに考えたのが、
x |= (0x100 - (x >> 8)); // 最大値を制限
x &= ~(0x100 - (x >> 31)) & 0xff; // 最小値を制限
または
x |= ((x >> 8) + 0x7f) ^ 0x7f; // 最大値を制限
x &= ((x >> 31) + 0x7f) ^ 0x80; // 最小値を制限
です。
最小値もある程度決めてしまって構わないのですが、
これ以上高速に値を得る方法はありませんか?
21:デフォルトの名無しさん
07/05/03 19:39:08
最小値がある程度小さいなら、最小値の制限は
x &= ~((unsigned)x >> 24);
でいいかと。
22:デフォルトの名無しさん
07/05/03 20:27:03
>>16 std::fill()
23:デフォルトの名無しさん
07/05/03 20:29:06
>>17,19
memset() は埋める値が 0 とか 0xff とかじゃないと使えないだろ。
24:デフォルトの名無しさん
07/05/03 22:17:18
>>21
それいいですね!
~の方が速そうなんですが、
最後は0xffでマスクしないとゴミがのる可能性があるので、
ちょっと変えて、((unsigned)x >> 24) ^ 0xff として使わせてもらいます。
ありがとうございました^^
25:デフォルトの名無しさん
07/05/03 22:19:57
あ、すまん。間違えてたわ。
その通り。
26:デフォルトの名無しさん
07/05/03 22:28:45
(unsigned)~x>>24
のほうが速そうに見える
27:デフォルトの名無しさん
07/05/03 22:33:07
なるほど。
28:デフォルトの名無しさん
07/05/03 23:22:19
>>26
たしかにそうですね。
と思い、コードを変更して計測してみました。
結果が、クロック単位でまったく同じだったのでおかしいと思い、
コンパイラの生成コードを見てみたのですが、、、
なんと、(((unsigned)x >> 24) ^ 0xff) が>>26とまったく同じようにコンパイルされてました
vc8すごい・・・
>>26さんもありがとうございました
29:デフォルトの名無しさん
07/05/03 23:46:17
コンパイラ<やれやれ、やっと俺の優秀さに気づいたか・・・
30:デフォルトの名無しさん
07/05/04 00:36:41
ダンゴさんに言わせれば、VCはクズだがな(笑)
31:・∀・)っ-○◎●
07/05/04 00:47:45
Pentium Pro時代の癖が抜けずに未だに
アドレッシングモード使うのを期待する場面で
ロード+レジスタ間オペレーションに展開する
VC++は駄目な子
32:・∀・)っ-○◎●
07/05/04 00:49:21
まあ、Intel謹製以外では一番マシだけどなw
33:デフォルトの名無しさん
07/05/04 01:17:32
C、C++の最適化について語るスレ -O2
いまさらだがスレタイはこんな感じのにスレばよかったのに。
34:デフォルトの名無しさん
07/05/04 12:45:30
AoSよりSoAの方が高速に動く理由を教えてください
35:デフォルトの名無しさん
07/05/04 20:37:59
C、C++の最適化についてダンゴ先生が篤く語るスレ
がいい
36:・∀・)っ-くコ:彡-
07/05/04 20:40:45
以下、団子に変わりましてイカがお送りします
37:デフォルトの名無しさん
07/05/05 17:06:49
関数の引数で、スタックのオーバーヘッドをなくす為に
const hoge_t& hoge なんて参照渡しが使われるけど
これってVC8とか今時のコンパイラでも意味ありますかね?
38:デフォルトの名無しさん
07/05/05 17:20:44
参照するとスタック使わなくなるわけでねえでがす
39:デフォルトの名無しさん
07/05/05 17:24:20
>>37
オブジェクトの作成を勝手に省略することは、
一部の例外を除いて規格上認められていないから、
今でも有効。
40:デフォルトの名無しさん
07/05/06 00:22:09
ま、ダンゴさんに言わせれば、VCはクズだがな(笑)
41:・∀・)っ-くコ:彡-
07/05/06 00:28:51
>>40はゴキブリかな
42:デフォルトの名無しさん
07/05/06 03:45:45
>>34
ものによるが、キャッシュが効きやすくなるか、ベクタ化しやすくなるか、ループの最適化をしやすくなる。
AoS の方がこれらに有効なこともあるので、ものによるとしか言えん。
43:デフォルトの名無しさん
07/05/08 00:40:06
グローバル変数Aを算出し、算出した関数内でAを参照したいときは、
①直読み
②算出時にローカル変数で一度算出しておき、それを参照(レジスタ参照で高速化を狙う)。Aは適当なところでローカル変数を代入
どちらがより良いソースコードになるでしょうか・・・。
①は見やすくてコード量も減りますが、いちいちRAMにアクセスしそうなので実行速度に懸念があります。
②はローカル変数を用いることにより実行速度の向上を狙いますが、コード量の増加(ローカル変数増えまくり)や
オブジェクトサイズに懸念があります。
いまいちどちらにしたらよいかの判断が出来ませぬ・・・。
みなさまはどうされてます?
44:デフォルトの名無しさん
07/05/08 00:43:33
よくわからんが、関数・グローバル変数あたり、
待避と復旧用のコードが増えるだけでそ?
あと、レジスタに振られたローカル変数は消えるから。
45:デフォルトの名無しさん
07/05/08 00:50:12
>>44
レスどうもです。
「関数・グローバル変数あたり」が分かりませんでしたが・・。
ローカル変数を用いてレジスタアクセスを狙っても結局スタックに退避したら
変わらないってことでしょうか?
46:デフォルトの名無しさん
07/05/08 01:15:00
実測するしかないだろ。常識的に考えて。
47:デフォルトの名無しさん
07/05/08 06:09:18
>>43
俺様用語で抽象的なコードの質問されてもなぁ。
自分で最低限のコードを書いて、コンパイラに最適化させてアセンブリ出力見比べてみなよ。
まぁ、>46って結論が待っているけど。
48:デフォルトの名無しさん
07/05/11 06:47:42
最適化第一法則 最適化するな
最適化第二法則 まだ最適化するな
の意味の深さがまだ理解できていないと見えるな。
49:・∀・)っ-くコ:彡-
07/05/12 08:40:11
GCCってforループのiをインクリメントからデクリメントに変えるだけで
性能上がったりするよな
VC++なんかはループの最適化だけはアグレッシブだから
ほとんど気にする必要ないんだが
50:デフォルトの名無しさん
07/05/12 12:15:26
終了条件がたまたま 0 だったりするからじゃなくて?
51:・∀・)っ-くコ:彡-
07/05/12 12:29:07
0との比較のほうが命令数が少なくてすむんだよ
52:デフォルトの名無しさん
07/05/12 13:31:43
restrictedが使えるコンパイラってアルの?
53:デフォルトの名無しさん
07/05/12 13:33:48
あります。
54:デフォルトの名無しさん
07/05/12 13:35:58
>>53
bcc32を使っているのですが、うまくいきません
55:デフォルトの名無しさん
07/05/12 13:40:26
そんなもんに期待する方が間違っています。
56:デフォルトの名無しさん
07/05/12 13:40:26
あとiccもダメでした。
57:デフォルトの名無しさん
07/05/12 13:41:43
iccではちゃんと使えます。
58:デフォルトの名無しさん
07/05/12 13:42:04
そんなもんに期待する方が間違っています。
59:・∀・)っ-くコ:彡-
07/05/12 13:44:27
iccは9.1あたりから対応してるはず。VC2005コンパチだし。
60:デフォルトの名無しさん
07/05/12 14:29:43
そもそも restricted じゃなくて restrict だな。
GCC も余裕で使える。
61:デフォルトの名無しさん
07/05/12 14:30:50
そんなもんに期待する方が間違っています。
62:デフォルトの名無しさん
07/05/12 17:19:55
VC++は、2005から__restrictが導入されている。
63:デフォルトの名無しさん
07/05/12 23:41:50
__ かよ。
C++ でも使えるってことなのかな?
64:デフォルトの名無しさん
07/05/13 00:06:03
VCはc99じゃないからね。
65:デフォルトの名無しさん
07/05/13 01:21:12
ダンゴ先生に言わせればVCはクズだしなw
66:・∀・)っ-くコ:彡-
07/05/13 01:45:59
>>65は屑
67:デフォルトの名無しさん
07/05/13 03:40:23
烏賊自重しろ
68:デフォルトの名無しさん
07/05/17 16:38:10
長い数式の場合、複数の文に分けて書いた方が最適化しやすいのでしょうか、それとも一気に一つの文に詰め込んでしまった方がよいのでしょうか?
69:デフォルトの名無しさん
07/05/17 16:42:45
場合による
70:デフォルトの名無しさん
07/05/17 16:43:21
っ 実測
71:デフォルトの名無しさん
07/05/17 17:04:13
そういう最適化は尚早な最適化や、個人の好みでしかない事の典型的な例
72:デフォルトの名無しさん
07/05/17 17:29:12
オーバーロードしてるような時は
コピーコンストラクタが実行されないように
分けた方がいいやね。
73:デフォルトの名無しさん
07/05/17 17:39:47
>>68
先ずは読み易く書き、適切なコンパイルオプションでコンパイルし、そこが速度上のネックになっていないか測定し、
ネックになっているようならそこで初めて、そこを抜き出して両方のケースを測定してみることだ。
まぁ、コンパイラが適当に最適化してくれるから大差ないと思うよ。
74:デフォルトの名無しさん
07/05/17 21:24:07
ダンゴさんの締めのレスが待ち遠しいな
75:デフォルトの名無しさん
07/05/18 01:59:50
団子って良く呼ばれるけど、
書き込んだら書き込んだで叩かれるんだよな
76:デフォルトの名無しさん
07/05/18 02:04:33
呼ばれてしゃしゃり出て叩かれることを学習させないと。
赤子と同じ。
77:デフォルトの名無しさん
07/05/18 08:26:43
赤子みたいなレスだなw
78:デフォルトの名無しさん
07/05/18 11:36:25
赤子はこれから学習するが
団子は学習した結果
79:デフォルトの名無しさん
07/05/18 13:50:28
スキルの無い奴の粘着人格攻撃を受けられれば、コテも一流だな。
団子の圧勝か・・・。
80:デフォルトの名無しさん
07/05/18 20:13:30
団子は好きだけど思い込みが激しいから反芻してから発言して欲しい。
オレモナー
81:デフォルトの名無しさん
07/05/18 20:43:54
試しに >>80 を反芻してみた。
込みいからが発言して欲モ激しから反芻してい団しい。
オレ子は好きだけど思ナー
82:デフォルトの名無しさん
07/05/18 21:04:05
団子が負けたところを見たことがない
はっきり言って最強
83:デフォルトの名無しさん
07/05/19 00:29:20
逃げるが勝ちってか
84:デフォルトの名無しさん
07/05/19 00:30:36
糞壁と一緒だな
85:・∀・)っ-くコ:彡-
07/05/19 00:38:34
お塩先生に負けますた
矢田亜希子たん取られますた
86:デフォルトの名無しさん
07/05/24 20:42:26
>81
どういうアルゴリズムを適用するとその並びになるのか教えてくれ
87:デフォルトの名無しさん
07/05/24 20:58:46
反芻アルゴリズム
攪拌ではない
88:デフォルトの名無しさん
07/06/07 10:55:11
vectorは[]でアクセスできますが、これってメモリ上でも連続しているということでしょうか?
配列と比べても、実行速度は変わらないと考えてよいのでしょうか?
89:デフォルトの名無しさん
07/06/07 11:01:05
最新の仕様では連続してる事が保証されてた気がする。
ただ、それは別に [ ] でアクセスできるからという理由ではない。
こいつは演算子オーバーロードされてるから。
例えば deque なんかも [ ] でアクセスできるけど、
こいつはメモリ上の連続性は保証されてない。
90:デフォルトの名無しさん
07/06/28 02:32:29
>>88
vectorは連続している事が保証されているので、いざとなったら先頭アドレスを取り出して配列としてアクセスすることも出来るよ。
あと、配列の[]やvectorのoperator[]は境界チェックをしないけど、vectorのat()は境界チェックをするよ。知ってたらごめんね。
91:デフォルトの名無しさん
07/06/28 17:21:44
>>88
逆に言えば、添え字演算子[]で読み書きできるからといって、
メモリ上で要素が連続している保障があるとは限らない。
dequeとかmapとか。
92:デフォルトの名無しさん
07/07/15 14:57:49
>88の人気に嫉妬
93:デフォルトの名無しさん
07/08/03 20:43:46
Intel compilerのx64版を使っているのですが、
レジスタにある筈の値を何度もメモリに読みにいったり、
もう使わないローカル変数をメモリに書き込んだりしています。
ループの奥底なので許容できません。VTune で見てもボトルネックになって
いるようです。
深い理由があってのことででしょうか?
それとも、x64版の熟成が未完なのでしょうか?
32bit版との賢さの違いについてどんな印象をお持ちですか?
94:デフォルトの名無しさん
07/08/03 21:19:37
64bit版は知らんけど、32bit版もインテルが自分で言うほど
飛びぬけた性能でもないような…。
体験版で試して、俺のプログラムはVCに全敗したから、買う
のやめた。Linuxだと他に選択肢が無いのかも知れんけどね。
95:デフォルトの名無しさん
07/08/03 21:42:37
ウチの場合はICCのが何割か速かったよ。画像処理で。
GCCとVCと比較してもっとも早かった。
64bit版はさすがに知らないけど。
マルチコアならレジスタにある値だけだとあんまり信用できないからかね?
96:デフォルトの名無しさん
07/08/03 22:02:01
ポインタをdereferenceした値なんじゃないの
97:デフォルトの名無しさん
07/08/04 01:58:07
>>93
const付けられるところには全て付けてるよな?
関数ローカルのauto変数とか、クラスのメンバ関数(not変数)とかにも。
それでエイリアス問題とかが片付くから、割と変わるぞ。
98:デフォルトの名無しさん
07/08/04 02:10:28
エイリアス問題はconstじゃ解決しないぞ
restrictキーワードが要る
99:デフォルトの名無しさん
07/08/04 03:29:23
ん?
メンバ関数がconstなら、その関数内から見たらクラスのメンバ変数は皆const扱いだろ?
となると、複数のポインタor参照でメンバ変数を参照したり、キャッシュを持ったりしても実害が無いだろ?
変更がありえないんだから。
つまりエイリアスが発生しても、それが問題にならないケースがあるわけだ。
(グローバル関数経由の変更というものもあるので、確実じゃないけどな)
もちろん、クラスのメンバ以外を操作するならrestrictが必要だな。
それはおっしゃる通り。
100:デフォルトの名無しさん
07/08/04 12:12:12
constは、「プログラマが」変数を書き換えないという表明であって、
値が変化しないことの保証にはならない。
ポインタor参照経由の値は、
常にaliasの可能性があるとコンパイラはみなさなければならない。
というか、最適化のためのconstnessの判断はコンパイラがやることなので、
最適化フェーズではregisterキーワードよろしく無視されると考えていい。
と似たことを以前constでメシがナンタラというスレで書いた気がする。
101:デフォルトの名無しさん
07/08/04 13:00:20
こういうことかな・・・?
class A{
public:
int x;
void foo(int*) const;
};
main(){
A *a = new A();
a->foo(&a->x);
}
void A::foo(int* p) const
{
int x1 = x;
*p += 1;
int x2 = x; // x 読み直し
}
102:デフォルトの名無しさん
07/08/04 15:53:02
うーん、そういうケースも多いだろうけど
constがオプティマイザに無視されるということはないと思うぞ。
以前関わったプロジェクトで、constがろくについていなかったので
片端から付けた事があるんだよ。
結果リリースビルドのバイナリが大幅に変わってしまった。
速度的にはそれほどの向上は無かったのが残念だけど(ホットスポットは変わらなかった)
全体的にconstメンバ関数のインライン化が行われていた。
約1%ほどバイナリが肥大化したのはご愛嬌^^;
103:デフォルトの名無しさん
07/08/04 16:08:05
そりゃまたアホなコンパイラだな・・・
それにその例だと、速度かわらず、バイナリが増えてるんなら無意味じゃないか。
104:デフォルトの名無しさん
07/08/04 16:12:56
ホットスポットが変わらないから速度の有意差が出なかったのだろ。
105:デフォルトの名無しさん
07/08/04 19:43:09
>>102
そこまで言うならメンバ関数への const の有無で出力コードの変わるソースを
出してみて欲しい。
106:デフォルトの名無しさん
07/08/05 01:23:48
ちょっとやってみたが、短いサンプルだとconstの有無に関わらずインライン展開されて
結局同じになってしまうな……
まあこの場合「const の有無で出力コードの変わるソース」が存在することを
証明できればいいのだから、最適化オプションの調整を含めて
もうちょっと詰めてみる。
こっちもデスマ中なので何日かかるかもしれないが、期待しないで待ってろ。
107:デフォルトの名無しさん
07/08/05 01:29:31
必要なのは「出力コードが変わる」じゃなくて「速度向上に貢献する」だぜ
つか、なにもデスマ中にやらんでも(´・∀・`)
元気なときにやろうぜ
108:デフォルトの名無しさん
07/08/05 02:29:18
いや、>>105がそう言っているんでな。
とりあえず「constで変わりうる」ということを出しておこうかなと。
C/C++では完全な参照透過性を保証する構文が無いから、
コンパイラにとって論理レベルでの最適化は難しいだろうが、
不可能では無い事を明示したい。
まあ今日は寝る。おやすみ。
109:デフォルトの名無しさん
07/08/05 02:56:49
>>108
そこまでわかっていて不可能ではないと思う根拠はなんだろう?
楽しみにしてるよ。
110:デフォルトの名無しさん
07/08/06 22:23:24
今年プログラム初めてまだまだわからないことだらけで助けてほしいことがある。
複数のファイルより条件に合う行を抜き出して一つのファイルに出力するプログラムを作ったんですが
処理に結構時間がかかってしまいます。何とか速度向上させたいのですが何か良い方法はないでしょうか?
本当は自分でいろいろ試行錯誤してやりたいのですが分け合って時間が取れなくて書き込みました。
111:デフォルトの名無しさん
07/08/06 22:26:47
グレップツール使いな
112:デフォルトの名無しさん
07/08/06 22:35:17
>>110
秀丸つかっとけ
113:デフォルトの名無しさん
07/08/06 22:36:36
>> 93 です。
色々アドバイス頂きながら、返信せず申し訳ありません。
const はきちんと付ける主義です。
わざわざ、{} を追加して、スコープを絞っても、ローカル変数の
無駄な書き込みを止めさせることはできませんでした。
何となく、ICC x64のコンパイル結果って回りくどい気がするのです。
命令のレイテンシとかキャッシュ効率とか考慮された結果かな?
114:デフォルトの名無しさん
07/08/06 22:40:25
restrictについては言及ナシですか。
115:デフォルトの名無しさん
07/08/06 23:06:13
つーか、具体的なコードも出さずにあーだこーだ言われても
「あーそうですか」としか言いようがないなぁ。
116:デフォルトの名無しさん
07/08/08 23:24:43
>>114
何故か書き込み不能になった返信がさらに遅れました。
restrictを使っても、コンパイル結果が同じでした。
仕事絡みなのでコードを出せません。ご了承下さい。
ごく一部を出しても、実害はないと思いますがバレると
厄介なことになりますもので...
117:デフォルトの名無しさん
07/08/08 23:26:13
別にその仕事とは全く関係ないコードを書けばいいのに。
118:デフォルトの名無しさん
07/08/09 02:19:54
○○○は糞、だけど証拠は出せません
いい流れだ
119:デフォルトの名無しさん
07/08/09 03:19:58
constによる最適化を主張する俺が戻ってきましたよ
とりあえずサンプルを作るのは諦めました。そこで
既存のプロジェクトからメンバ関数のconstを外す ⇒ エラーが出たところだけconstに戻す
という手順で相違点を調べました。(バージョン管理ツールは便利だねえ)
>>102の環境はVC7.1でしたがライセンスの関係で問題があるので
今回の環境は別のプロジェクトのCodeWarriorです。
で、リリースビルドの結果は以下の通り。
全関数(メンバ関数でないものやライブラリも含む) 12256個
constメンバ関数 253個
検証時にconstを削除出来なかったメンバ関数 24個
const削除前のコードサイズ 2899400 bytes
const削除後のコードサイズ 2899084 bytes
constを付けた方がコードサイズが増える傾向がありますが、CodeWarriorの場合は
インラインされやすくなるという傾向はありませんでした。
また、極端にパフォーマンスが変化するということはありませんでした。
(づづく)
120:デフォルトの名無しさん
07/08/09 03:40:23
逆アセンブリで見られる具体的な差異としては
const有りだと分岐命令の後に来ている命令が
const無しだと分岐命令の前に来ている
という現象が所々に見られました。
いつ評価しても同じなら分岐の後で評価したほうが得、ということなんでしょうか。
(遅延評価に似てる?)
サンプルを上げようかと思ったけど、きわめて眠いのでまた今度。
明日か明後日までに適当なアップローダの紹介を希望。
ではおやすみなさい。
121:デフォルトの名無しさん
07/08/09 07:15:32
分岐命令をまたいで命令が移動するってのは、動作が変わってるような気がする。
よくわからんからサンプルが欲しいな。ろだ↓
URLリンク(kansai2channeler.hp.infoseek.co.jp)
122:デフォルトの名無しさん
07/08/09 10:42:03
ほい、上げておいた。
URLリンク(kansai2channeler.hp.infoseek.co.jp)
全部上げるわけにもいかんので加工してある。
詳細は添付のreadme.txtを読んでくれ。
じゃ俺は戦場に戻る。
123:デフォルトの名無しさん
07/08/10 09:31:04
>>122
リストファイル中のソースとの対応がずれてたり、命令数の違いでアドレス部が
ずれてたりしてるけど、本当に命令レベルの違いだけを抽出すると、2箇所だけになった。
--
const無し:
lw v1,-21056(v0)
addiu a0,v1,436
lw v1,436(v1)
const付き:
lw a0,-20672(v0)
lw v1,436(a0)
--
const無し:
lw v0,-21056(v0)
addiu v1,v0,436
lw v0,436(v0)
const付き:
lw v1,-20672(v0)
lw v0,436(v1)
--
124:123
07/08/10 09:54:07
2箇所いずれも app->CheckMenu() のところね。逆読みすると、
app 内のポインタが指す配列か構造体から1つ値を読み出してるって感じ
なんだけど、やっぱり CheckMenu() のソースが欲しいな。ダメ?
const無しのほうにある addiu の結果は使われて無いように見える。
あれ? const 付けたほうがコード増えるって言ってたけど、ここでは
1命令減ってるね。
125:123
07/08/10 10:03:26
const の有無で最適化に影響が出てるんじゃなくて、オーバーロードに影響が
出て処理が変わってるだけじゃないだろうか?
たとえば std::bitset::operator [] (size_t) なんかだと、 const 版は単に bool が
返るけど、非 const 版は代入もできるプロキシオブジェクトが返るのでかなり
違った処理になるはず。
126:123
07/08/10 10:31:24
あ、 addiu の結果はその後の sw で使われるみたい。
app のメンバオブジェクトについて const 版が int を返して、
非 const 版が int& を返すようなオーバーロードが使われてる予感。
んで int& だと続く書き込みに使いまわせるからレジスタに置かれた、と。
127:デフォルトの名無しさん
07/08/10 11:09:19
やっぱり、単純にはなんとも言えないという結論か。
128:デフォルトの名無しさん
07/08/10 21:42:46
いや、大方の予想通りメンバ関数の const は最適化の助けにはならないって結論だろう。
129:デフォルトの名無しさん
07/08/12 22:50:05
お待たせしました。一時帰宅しました。
辛辣なツッコミを期待していたんだけど、ちょっと物足りないかしら。
まあ、相手してくれてありがとう。
以下質問に対するごお返答。
>>122
CheckMenu()は以下のようなコードになっている。オーバーロードはされていない。
bool CApplication::CheckMenu(int n) { return (m_MenuStatus == n); }
ちなみにappはCApplication型のグローバル変数。constではない。
>>128
出力バイナリは違っているのに、そう言いきれるのはなぜ?
130:デフォルトの名無しさん
07/08/12 22:51:52
小林洋平
131:デフォルトの名無しさん
07/08/12 23:42:01
>>129
関数の中身を晒してくれてありがとう。そういうことなら、素の int 型メンバ変数の
読み取りについてコンパイラ内部で >>126 の言うオーバーロードと似たような扱いが
されているんだろう。
今回の例では const が無い場合に int& をキャッシュするために命令数が一つ
増えたとすると、前後の処理内容によってはその int& のキャッシュによって効率が
上がることも考えられる。いつでも const を付けたほうが効率が良いとは言えない。
今回の例で、コンパイラが const 無しの場合に const 付きの場合と同じコードを
吐いても何ら規格に違反しない。最適化の詰めが甘かっただけとも言える。
132:デフォルトの名無しさん
07/08/13 10:42:15
constは保守のための手助けみたいなもんだろ
mutableしてない変数に代入しようとしてたらエラー吐くだけの
133:デフォルトの名無しさん
07/08/13 14:57:53
gcc の _attribute((const)) みたいなもんがあればいいのかも。
・関数の戻り値が引数とインスタンスの内容にのみ依存する。
つまり、
class Test {
public:
int foo() __attribute__((const));
void bar() const;
};
Test T;
int a = T.foo();
T.bar();
int b = T.foo(); // int b = a; に最適化できる。
134:デフォルトの名無しさん
07/08/14 02:07:27
>>132
変数定義時の const はそうでもないよ。 const 付きで宣言された変数は
ポインタや参照を関数に渡した後でも、値が元のままであることを期待して
最適化してもいい。
これに対してポインタ・参照の指す先の型や、メンバ関数に付ける const は
ほとんどコード生成に影響しないという話。
135:デフォルトの名無しさん
07/08/14 02:10:47
>>133
それはダメでしょ。
T の宣言に const が付いてないので T.bar() の中で const_cast して
値を変更しても合法なはず。
136:デフォルトの名無しさん
07/08/14 02:59:32
intメンバ変数一個のstructで試してみたが、
>ポインタや参照を関数に渡した後
では読み直しをやってるなあ。
環境はVC8とgcc3.4.4(cygwin)
137:デフォルトの名無しさん
07/08/14 03:34:58
>>136
どんなソースで試したの?
以下のソースだと s に対する const によって読み直しが消えて return 10 に最適化される。
const 外すと当然メモリ上の s.x が読み出される。
struct S { int x; };
void f(struct S const* p);
int g(void)
{
struct S const s = { 10 };
f(&s);
return s.x;
}
138:137
07/08/14 03:35:31
あ、確認した環境は Cygwin gcc 3.4.4 の -O3 ね。
139:デフォルトの名無しさん
07/08/14 09:55:00
似せるとこういう感じ。gccは-O3、vc8は/Oxです。
struct S { S(int x_):x(x_){} int x; };
void f(struct S const * p);
int g(void)
{
struct S const s(10);
f(&s);
return s.x;
}
つーか分からないのは仕方ないか。ということで
struct S { S(int x_):x(x_){} int x; int getX() const { return x; } };
void f(struct S const * p);
int h(int);
int g(void)
{
struct S const s(10);
h(s.getX());
f(&s);
return s.getX();
}
vc8もgcc3.4.4も、分かってるんだか分かってないんだか分からないコードを吐く。
さらに、このコードの int x を const int x にすると、gccは読み直しをしなくなる。
これはsのconst修飾に依存しない。(あれれ?)
140:デフォルトの名無しさん
07/08/14 10:20:39
>>139
ほんとだ。これは期待はずれだなぁ。
コンストラクタ内での代入を許すために const として定義されたという情報が
途切れてしまっている、って感じ?
メンバのほうに const を付ければ代入を許すタイミングは無いから、 >>137 と
同様に最適化できる、と。
141:デフォルトの名無しさん
07/08/21 08:34:45
const 談義中に割り込み質問ですみません。
VTune で、Clockticks をサンプリングすると"No Samples were collected."
になってしまいます。
Sample After Value を変えろ、との記述を見つけて試しましたが、
うまくいきません。(他の event は収集できます)
対策をご存知の方はいらっしゃらないでしょうか?
142:デフォルトの名無しさん
07/08/21 21:48:51
>>141 です。自己解決しました。
使っていたのが一つ前のバージョンのVTune だったので、
quad core に対応していなかったようです。
最新版の体験版をインストールしたらうまくいきました。
それにしても、何のエラーメッセージも出ず、Clockticks
だけ収集できないとは、恐ろしい。
143:デフォルトの名無しさん
07/08/25 12:59:29
switchの場合分けにおいて、記述したcase以外は絶対にありえないと
コンパイラにヒント出す方法って無いですか?
分岐の先頭でcase以外を範囲外として弾くのが状況として
ありえないのでもったいないです。
環境非依存でもVC6,7,8限定の方法でもかまいません。
よろしくお願いします。
144:デフォルトの名無しさん
07/08/25 13:51:02
>>143
こういう場合だったら、
switch(hoge)
{
case 1:
//1の処理
case 2:
//2の処理
default:
//ここに来ることは絶対にない
}
こうすればいいんでないの?
switch(hoge)
{
case 1:
//1の処理
default:
//2の処理
}
145:デフォルトの名無しさん
07/08/25 13:58:11
>>143
環境非依存ではそんなものはない。
c++であれば、enum型を使うことで慮ってくれるコンパイラがあるかもしれない。
146:デフォルトの名無しさん
07/08/25 14:40:46
>>144
アセンブラコードを見てみたところ
1・範囲外チェック
2・テーブルジャンプ
という流れにコンパイルされていました。
case 1:
//1の処理
default:
//2の処理
これだとdefaultの処理+テーブルジャンプの処理になってしまって、
結果的に範囲外チェックしているのと負荷は変わらないようです。
>>145
enum試してみます。
ありがとうございました。
147:143
07/08/25 14:41:25
sage失敗すみません
148:デフォルトの名無しさん
07/08/25 14:51:29
VC7以降なら __assume を使え
149:144
07/08/25 15:11:09
>>146
なるほど。こちらが勉強させてもらいました。
確かに範囲外だったら大変だから、コンパイラとしてはチェックせざるをえないんだね。
150:デフォルトの名無しさん
07/08/25 15:28:49
>>143
>144の前者のケースなら、
switch (hoge)
{
case 1:
...;
case 2:
default:
...;
}
でいいんでない?
151:デフォルトの名無しさん
07/08/25 15:29:37
つーか、二項しかないのにテーブルジャンプにしか最適化できないコンパイラが蛸な希ガス。
152:143
07/08/25 15:41:13
>>148
__assumeが意図にかなっているようです。ありがとうございました。
153:デフォルトの名無しさん
07/08/25 20:23:00
>>143
gcc限定ならコメントでなんか記述すればコンパイラが理解してくれた気がする。
154:・∀・)っ-くコ:彡-
07/08/25 20:54:24
関数テーブル+__forceinlineじゃ駄目だったっけ
155:デフォルトの名無しさん
07/08/25 21:02:19
gccはassert()が__assumeと同じ動作したはず。
156:デフォルトの名無しさん
07/09/24 00:02:22
assert(0);だな
157:デフォルトの名無しさん
07/09/24 13:53:56
♪ ∧,, ∧ ♪
♪ ∧,, ∧´・ω・) 美脚♪
∧,, ∧´・ω・) )
♪∧,, ∧´・ω・) )っ__フ ♪ ∧,, ∧
∧,, ∧´・ω・) )っ__フ(_/ 彡 .∧,, ∧ )
(´・ω・) )っ__フ(_/彡 ∧,, ∧ ) )
(っ )っ__フ(_/彡 .∧,, ∧ ) ) Οノ
( __フ(_/彡 ∧,, ∧ ) ) Οノ ヽ_)
(_/彡 ( ) ) Οノ 'ヽ_)
( ) Οノ 'ヽ_)
(ゝ. Οノ 'ヽ_) ♪
♪ ミ ヽ_)
158:デフォルトの名無しさん
07/10/06 14:06:35
C++特有じゃないとは思いますが質問させてください。
ある処理をループしようと思っているんですが、その時に、
カーソルとして使用するポインタを(ローカル変数として)毎回宣言するのと、
あらかじめ外部で宣言したものを使いまわすのではどちらが高速なのでしょうか?
159:デフォルトの名無しさん
07/10/06 14:39:57
>>158
大丈夫、そんなもんは真っ先にコンパイラの最適化の餌食になるから。
それ以前に、ポインタで回すよりも配列参照で回す方が速いかも知れない。
いずれにしても、ケース・バイ・ケースだから実測するべし。
160:デフォルトの名無しさん
07/10/06 14:41:04
♪ ∧,, ∧ ♪
♪ ∧,, ∧´・ω・) 美脚♪
∧,, ∧´・ω・) )
♪∧,, ∧´・ω・) )っ__フ ♪ ∧,, ∧
∧,, ∧´・ω・) )っ__フ(_/ 彡 .∧,, ∧ )
(´・ω・) )っ__フ(_/彡 ∧,, ∧ ) )
(っ )っ__フ(_/彡 .∧,, ∧ ) ) Οノ
( __フ(_/彡 ∧,, ∧ ) ) Οノ ヽ_)
(_/彡 ( ) ) Οノ 'ヽ_)
( ) Οノ 'ヽ_)
(ゝ. Οノ 'ヽ_) ♪
♪ ミ ヽ_)
161:158
07/10/06 15:01:50
>>159
なるほど。コンパイラに頼れそうですね。
配列については任意の位置に追加、削除等の関係から使えませんでした。
ありがとうございました。
162:poooh ◆manko/yek.
07/10/06 16:10:39
グローバル変数は最適化に良くない。これ豆知識な。
163:デフォルトの名無しさん
07/10/06 17:34:59
グローバル変数は最適化に良い。これ豆知識な。
164:デフォルトの名無しさん
07/10/06 17:54:04
確かに、既存ソフトの高速化の仕事をしていると、グローバル変数があったら狙い目だとは思うけどね。
165:デフォルトの名無しさん
07/10/06 18:27:36
>>164
高速化の仕事ってどんな感じなの?
今の職場では高速化の効果が工数の割に合わないと言われることが多くて
バグ改修時についでに高速化する程度しかやらせて貰えない。
既存機能を維持しつつどうやって安全に高速化してるの?
グローバル変数触るなら単体テストだけじゃ足りないよね?
166:デフォルトの名無しさん
07/10/06 20:10:46
既存機能を維持しないでどうやって危険に高速化してるの?
そんなんだからやらせて貰えないんだぜw?
167:デフォルトの名無しさん
07/10/06 20:12:21
単体テストで完全に見えるスコープで、グローバル使いまくる馬鹿は沢山いる
168:164
07/10/06 21:00:33
高速化で受ける業務はソースで引き渡しだから、コード解析結果と単体テスト結果しか出さない罠。
169:165
07/10/06 21:36:19
>>168
高速化で受けた業務なら性能試験はやるんじゃないの?
単体テストしかしないなら関数単位の高速化なのかな? ライブラリ系?
参考までに、使ってる測定ツールとか教えてくれないかな。
それにしても、コード解析結果と単体テスト結果で話がつくとはな。
俺んとこだと結合試験と性能試験やらずに改修完了なんてまず了承されないよ。
170:デフォルトの名無しさん
07/10/06 21:53:07
そりゃぁ、「何」で金取っているかの違いだろ。
依頼主だって全部の環境晒せるような物ばかりとは限らんわけだし。
171:デフォルトの名無しさん
07/10/06 22:17:43
結合と性試験やらずに
172:デフォルトの名無しさん
07/10/07 21:26:42
単体テスト=手淫
173:デフォルトの名無しさん
07/10/11 07:30:27
♪ ∧,, ∧ ♪
♪ ∧,, ∧´・ω・) 美脚♪
∧,, ∧´・ω・) )
♪∧,, ∧´・ω・) )っ__フ ♪ ∧,, ∧
∧,, ∧´・ω・) )っ__フ(_/ 彡 .∧,, ∧ )
(´・ω・) )っ__フ(_/彡 ∧,, ∧ ) )
(っ )っ__フ(_/彡 .∧,, ∧ ) ) Οノ
( __フ(_/彡 ∧,, ∧ ) ) Οノ ヽ_)
(_/彡 ( ) ) Οノ 'ヽ_)
( ) Οノ 'ヽ_)
(ゝ. Οノ 'ヽ_) ♪
♪ ミ ヽ_)
174:デフォルトの名無しさん
07/10/17 08:10:23
for (int i=10;i--;)
{
//ループの中身
}
って
for (int i=0;i<10;i++)
{
//ループの中身
}
より高速?
175:デフォルトの名無しさん
07/10/17 10:40:19
>>174
上の方がループの回数が多いから遅い。
176:デフォルトの名無しさん
07/10/17 12:55:44
すみません
for (int i=0;i<9;i++)
{
//ループの中身
}
でした
177:デフォルトの名無しさん
07/10/17 13:16:29
>>176
>175は間違い。>174でループ回数は同じになっている。
で、どちらも同じ速度のコードになったよ(icc -fastで)。
実測したら、後者の方が気持ち速かった。と言っても、差は10msオーダーだけど。
--
for (int i = 0x7000 * 0x10000; i--;) func();
for (int i = 0; i < 0x7000 * 0x10000; i++) func();
--
178:デフォルトの名無しさん
07/10/17 13:32:58
速度は実測が基本。
179:デフォルトの名無しさん
07/10/17 15:04:30
>>177
ありがとう、やっぱりふつうに記述した方が、コンパイラにとってもいいようですね。
180:・∀・)っ-くコ:彡-
07/10/18 00:31:08
forよりdo-whileが速い。
まあ自動で最適化してくれるけど
181:デフォルトの名無しさん
07/10/18 10:54:47
/*1*/
for (i = 0; i < n; i++)
これと、誘導変数を使った
/*2*/
for (ii = -n; ii < 0; ii++)
i = n + ii;
それぞれについて、生成コードを予想
また実際の処理系に生成させたコードを評価せよ (n点)
182:デフォルトの名無しさん
07/10/18 12:17:32
変数の型が分からないと予想できねえよ。
183:デフォルトの名無しさん
07/10/18 12:38:28
nは正数?
184:デフォルトの名無しさん
07/10/18 12:41:36
クラスかもな。
185:デフォルトの名無しさん
07/10/18 13:05:00
宿題?
186:デフォルトの名無しさん
07/10/18 13:39:29
実行コストについてはダウンカウンタと大差ない感じ。
こりゃ使える。いただき。
a[i]みたいにiをインデックスで使う場面では
a[n+ii]に対して&a[n]==a+nがループ内不変になるね。
つかiは符号付き整数だろw
で、おれ何点?
187:519
07/10/18 13:41:59
for文の中身は?変数がintだとすると
for (i = 0; i < n; i++);
は i=n; という式に展開される可能性がある。
for (ii = -n; ii < 0; ii++) i = n + ii;
もnが定数ならば定数代入式に展開される可能性がある。
ていう最適化機能がgccにあったような…?記憶違い?
188:デフォルトの名無しさん
07/10/18 16:04:41
空ループの話で盛り上がって 参りました
189:デフォルトの名無しさん
07/10/18 16:18:58
全然
190:デフォルトの名無しさん
07/10/19 09:21:06
乱数が100個必要だとして、単にループで100回乱数を発生させるのではなく、
1つの乱数から、分割するなどして100個効率よく発生させることはできないでしょうか?
191:デフォルトの名無しさん
07/10/19 09:28:51
分割って何?
並列化するってこと?
100個乱数拾うだけならたいした変化は無いと思われ
192:デフォルトの名無しさん
07/10/19 09:43:07
使い道や欲しい乱数の範囲など具体的に
193:デフォルトの名無しさん
07/10/19 12:21:09
MTなら実装によっては624個の乱数が一度に得られる
でも内部的にはループだしな
194:デフォルトの名無しさん
07/10/19 18:51:21
>>190
64bitの乱数があったとしてそれをそれを8bit区切りに4つに分けて
8bitの乱数4つとして使えるかってこと?
乱数の質は悪くなると思うけど、どうだろ?
195:190
07/10/20 05:36:18
用途はモンテカルロシミュレーションです。
現在はMTを使っています。
計算精度は32bitのfloatでやっているのですが、乱数は64bitのdoubleなので、
それを単純に上位と下位に分けて、一回で2回分使えないかと考えています。
もうひとつ考えているのは、64bitで生成された乱数を、ローテートで1bitずつずらして
一回のMTで64個の乱数が生成できないかということです。
ただ、この場合、乱数の質が元のMTに対してどのようになってくるのかがわかりません。
196:デフォルトの名無しさん
07/10/20 05:45:19
MTやめてXorShift使うとか
197:デフォルトの名無しさん
07/10/20 06:46:44
>>195
少なくとも2番目の方法はいくない。
例えば一番左のビットが0の場合、左にローテートしたら元の数の2倍になる。
つまり64個の乱数の中に、大量のaとa*2が入り込む非常に膣の悪い乱数になるよ。
198:デフォルトの名無しさん
07/10/20 07:42:54
>膣の悪い乱数
乱れすぎw
199:デフォルトの名無しさん
07/10/20 08:45:07
>>195
最初の方法もダメ。
MTのdoubleは基本的に仮数部32bitなので分割した下の方は精度が腐る。
仮数部53bitの方は乱数を2個使っているし。
200:190
07/10/20 10:15:36
皆さんありがとうございます。
とりあえず、2^128-1周期のXorShiftを使ってみようと思います。
ところでXorShiftのseedのとり方ですが、オリジナルの文献では
x=123456789,y=362436069,z=521288629,w=88675123;
となっていますが、たとえば、x=1,y=2,z=3,w=4;とすると最初の
数十個は
2061
6175
4
8224
4194381
8396986
8388750
25174430
8652983179
25875070649
8636205711
60369541016
17600805477257
35210146488062
52785194351115
70428979519260
36239912164446735
ように非常に悪い乱数系列になってしまいます。
最初の数百個を捨てればよいのかもしれませんが、seedの選び方には何か決まりがあるのでしょうか?
201:デフォルトの名無しさん
07/10/20 13:19:11
>>190
sineくれくれ厨
202:デフォルトの名無しさん
07/10/20 14:14:15
お前がsine
203:デフォルトの名無しさん
07/10/20 15:24:11
>>200
質が悪いって言うけど、どの一部を取り出してもそういった偏りが全く無いほうが質が悪いでしょ。
固定の種にしたいなら好きなだけ選びなよ。
204:デフォルトの名無しさん
07/10/20 15:28:19
つーか擬似乱数スレでやれよ
205:デフォルトの名無しさん
07/10/20 15:58:23
sine、cosine
206:デフォルトの名無しさん
07/10/20 17:18:59
tangent
207:デフォルトの名無しさん
07/10/20 19:44:18
cosecant
208:デフォルトの名無しさん
07/10/21 00:53:23
俺には >>200 の乱数列のどこが質が悪いのか分からん
誰か説明してくれ
209:デフォルトの名無しさん
07/10/21 12:35:59
>>208
このスレは馬鹿なお前のためにあるんじゃない
210:デフォルトの名無しさん
07/10/21 19:33:52
>>200
乱数の種で複数の値とるとき
互いに素ってのと2の累乗を自分は使わないようにしているけど…
根拠がない。それに小さすぎる値も使わないようにしている。(1とか2とか…)
211:デフォルトの名無しさん
07/10/23 01:51:46
>>200
void srand_xor128(void){ w^=(unsigned)time(0)*1812433253; }
とかwだけ変更すればたぶんおk。心配なら最初の十万個位捨てたら。
212:デフォルトの名無しさん
07/11/07 04:00:14
PSP用ゲームのVCとGCCの両用ソースなんですが
関数内でstaticな配列を使ってはならないという社内ルールが付けられているんですが
理由わかります?
void hoge()
{
static const int array[100] = { 123, 456, 789, 123, 456, 789, };
,,,,
}
このようなstaticは駄目で
const int array[100] = { 123, 456, 789, 123, 456, 789, };
にしろということなのです。
メモリが厳しいらしいのですが、これで本当に節約になるんでしょうか。
213:デフォルトの名無しさん
07/11/07 04:34:13
>>212
実際にコンパイルしてアセンブリ出力を眺めてみれば?
前者は静的領域に確保されることが保障されていて消えることは多分ないが、
後者は最適化で消える可能性がある。
しかし、後者は静的領域からスタックにコピーする最悪なコードになるかもしれない。
それはさておき、100要素指定しておいて6個しかないと激しく無駄だと思う。
214:デフォルトの名無しさん
07/11/07 04:36:44
>>212
メモリの節約にはならないだろう。
一般的な実装を予測すると、 static をはずしてもスタックに確保された配列を
初期化するためのコピー元となる配列が作られてしまう。この初期値の配列が
static をつけた場合に確保される実体と同等のはずなので、 static をはずすと
スタックの領域と初期化用コピーの処理時間が余計に増えるだけになる。
動作上の違いは、再帰呼び出ししたときに配列のアドレスが別物になるかどうか、
という点しかないはず。
はっきり言って逆効果だろう。そのルール決めた人に理由を問い詰めたほうがいい。
非 const な変数に限ってローカル static を禁止するのなら、メンテナンス性の観点から
まだ理解できる。
215:デフォルトの名無しさん
07/11/07 04:56:45
次に静的記憶域期間(static)です。
こちらは宣言されている場所にかかわらずプログラムの開始直前にメモリを確
保し初期化します。初期化を忘れた場合値は0になります。
また、確保された領域はプログラムが終了するまで保持されるので関数の終了
時に値が消えることがありません。2回目以降関数内のstaticオブジェクトを
利用するときは前回の値から始まります。
216:デフォルトの名無しさん
07/11/07 05:00:13
もっとも時間食っているところ、メモリ食っているところを押さえればよい
あとはいちいち細かいモジュールに制限加えることはない
217:デフォルトの名無しさん
07/11/07 10:01:37
>>212
逆(実際はstatic推奨)か、厳しいのはスタックか。
218:デフォルトの名無しさん
07/11/07 10:40:48
400バイトくらいで厳しいのかよ
2M = 2000000バイトくらいは使用できるんだろ? 400を繰り返し使ってメモリリークするとかなら
考慮するひつようあるだろうけど使用後に解放されるなら他のプログラムに影響しないと思うが
500K = 500000バイトくらい使うところから節約しろよ
219:デフォルトの名無しさん
07/11/07 10:54:42
for (int i=0;i<100;i++)
a[i]=b[i]*xx;
だと問題なくベクトル化されるのですが
for (int i=0;i<100;i++)
a[i]=a[i]*xx;
だと
remark: loop was not vectorized: dereference too complex.
となってベクトル化されません。
自分自身が式の中に入っているとベクトル化できないのでしょうか?
コンパイラはicc ver 10で、OSはFedora 7です。
220:デフォルトの名無しさん
07/11/07 11:05:35
ベクトル化がわからない
配列に掛け算できないならコンパイラが壊れている
221:デフォルトの名無しさん
07/11/07 11:08:34
>>219
非常にシンプルなサンプルを作って試したら、どちらのケースもベクタ化できるようだよ。
配列aが何か特殊なことになってないかい?
再現できるソースは貼れないかな?
222:212
07/11/07 20:11:28
ありがとうございました。
私は開発機でコンパイルする権限も無い下っ端なのですが、
腑に落ちなかったモヤモヤが少し晴れました。
223:デフォルトの名無しさん
07/11/10 05:11:33
ループを200回くらい繰り返すとき、全部展開しておいた方が速いですか
インライン展開とかも出来て
あと、1万回するときに100回と100個展開した方が良いですか?
224:デフォルトの名無しさん
07/11/10 05:14:18
>>223
余計なことせずにコンパイラに全て任せるのが正解だ。
225:デフォルトの名無しさん
07/11/10 05:17:58
基本がなってない奴は気にするだけ無駄
226:デフォルトの名無しさん
07/11/10 06:01:10
誰かいませんか!
助けてください!!
227:デフォルトの名無しさん
07/11/10 06:04:49
どうしたの
228:デフォルトの名無しさん
07/11/10 06:08:40
スレ違いかもしれませんが
C言語の宿題がわからなくてこまってます!
明日ってか今日までなんです~
一緒に考えてくれる人いませんか?
お願い助けて~
229:デフォルトの名無しさん
07/11/10 06:28:53
宿題スレで聞けば?
って既にマルチしてるな。
230:デフォルトの名無しさん
07/11/13 17:18:26
staticだとスレッドセーフじゃなくなるよね?
231:デフォルトの名無しさん
07/11/13 17:20:17
場合による
232:デフォルトの名無しさん
07/11/14 00:43:45
>>230
読み込みのみなら気にしなくていい
書き込みが絡む場合はスレッドセーフではない
手軽にスレッドセーフにしてくれる拡張構文も最近はあったりする
(スレッドローカルストレージ)
233:デフォルトの名無しさん
07/11/14 08:05:03
>>232
初期化のときに問題にならない?
234:デフォルトの名無しさん
07/11/14 08:42:09
static変数の初期化より先にどこかでスレッド走らせ始めるつもりか
235:デフォルトの名無しさん
07/11/14 10:03:36
お前ら Binary Hacks の Hack 37 読むといいですよ
236:デフォルトの名無しさん
07/11/14 11:48:44
今日Binary Hacks買ってきたにょー
予定つまってて2週間ほど読めないけど…
237:デフォルトの名無しさん
07/11/14 12:42:42
Linux系の本だと思ってスルーしてたけど、Windowsプログラミングにはどう?
238:デフォルトの名無しさん
07/11/14 16:04:29
かったはいいがぱらぱらめくっただけな自分は
やはりLinuxの本という印象。
Windowsしかまともに開発してないから
あんまり楽しめなかった。
239:デフォルトの名無しさん
07/11/14 22:45:13
mallocダメ絶対な俺としてはスタック領域の調べ方Windows版が載ってただけで大満足
240:デフォルトの名無しさん
07/11/14 23:21:09
>>238
ありがとう。やっぱりそうか。
241:デフォルトの名無しさん
07/12/24 08:55:43
age
242:デフォルトの名無しさん
07/12/24 12:22:50
newの遅さはどうしてる~?
243:デフォルトの名無しさん
07/12/24 12:26:18
pool allocator使う
244:デフォルトの名無しさん
08/01/01 19:54:17
あげ
245:デフォルトの名無しさん
08/01/14 22:48:15
V(・∀・)V
246:デフォルトの名無しさん
08/01/22 15:39:00
割る2、掛ける2はシフトを使うと速い。
これ豆知識な。
247:デフォルトの名無しさん
08/01/22 15:52:07
俺のCPUは割り算よりシフトの方が時間かかるんだけど
248:デフォルトの名無しさん
08/01/22 16:53:00
最近のCPUではよくあることだな。
「1足すならaddよりincの方が速い」とかも同様。
俺の様なジジイの豆知識はほとんど役に立たん。
249:デフォルトの名無しさん
08/01/22 16:57:45
C/C++の範囲では、どっちがいいかなんてコンパイラの最適化に任せるのが正解。
250:デフォルトの名無しさん
08/01/22 18:22:31
いや、それを言っちゃうとこのスレ終わっちゃう。
つうか、だから伸びないんだなorz
VCの吐くコードとか見てると感動するけど、時々「?」と感じるときがあるのも事実。
そういうのを減らすための豆知識とか、誰か披露してくれまいか。
251:デフォルトの名無しさん
08/01/22 18:51:09
それじゃ、「?」と感じたものを挙げてみてくれ。可能な限り、説明しようじゃないか。
252:デフォルトの名無しさん
08/01/22 21:23:21
inc は使うなというのは正式な資料に書いてあるが
>俺のCPUは割り算よりシフトの方が時間かかるんだけど
こういうCPUは寡聞にして知らない.教えてくれないか?
253:デフォルトの名無しさん
08/01/22 21:27:30
割り算は普通遅いからね。
254:デフォルトの名無しさん
08/01/22 21:34:13
定数の乗除は最適化してくれるんじゃないの?
255:デフォルトの名無しさん
08/01/22 21:42:07
CPU はって言ってるからには
アセンブリで比較してると信じたいのだが・・・
C でやってる悪寒
256:デフォルトの名無しさん
08/01/22 22:18:22
まあ、バレルシフタ持ってない CPU だと、それなりに時間かかるからな。
3ビットのシフトの方が÷2より時間がかかる
と言う詭弁は可能かと。
257:デフォルトの名無しさん
08/01/23 03:30:02
割り算を逆数近似で計算してればあり得る?
まともな割り算は必ずシフタ使うから普通はないが.
258:デフォルトの名無しさん
08/01/24 14:02:42
デバッグで実行しての実測なんて意味がない、ただただ使う側のPCスペックと環境だけ
259:デフォルトの名無しさん
08/01/24 15:54:31
何の話だ?
260:デフォルトの名無しさん
08/01/25 00:01:50
foreachの最適化は無理無理無理無理いいいいいいいいいいいいいいいいいい
261:デフォルトの名無しさん
08/01/25 11:22:17
PenrynだとRadix-16のおかげでdivのクロック数は最小で6
昔とはだいぶ違うよ
262:デフォルトの名無しさん
08/01/25 13:52:45
>>261
あれ、14じゃね?
263:デフォルトの名無しさん
08/01/29 12:42:52
if((a == 1) && (b == 1)){ asdf; } という処理は論理積 && を使っている以上、分岐が2つある
if(a == 1){ if(b == 1){ asdf } } に等しくて、これだと条件分岐が多くその分投機予想も外れる可能性があがるので
if((a == 1) & (b == 1)){ asdf; } にすべきだ、っていう話を聞いたんですが、これは本当なんでしょうか?
もしくは、そんな事は演算子がオーバーロードされていない限り明確に分かりきった事なので
あらかじめコンパイラが論理積を (a == 1) & (a == 1) と同等の処理に最適化してくれたりとかはないんでしょうか?
264:デフォルトの名無しさん
08/01/29 12:57:59
>>263
実験してみた。最適化できるみたい。
$ cat test.c
void g(void);
void f(int a, int b) { if ((a == 1) && (b == 1)) { g(); } }
$ gcc --version
gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -S -o - -Os test.c
.file "test.c"
.text
.globl _f
.def _f; .scl 2; .type 32; .endef
_f:
pushl %ebp
movl %esp, %ebp
cmpl $1, 8(%ebp)
sete %al
xorl %edx, %edx
cmpl $1, 12(%ebp)
sete %dl
testl %eax, %edx
je L1
popl %ebp
jmp _g
L1:
popl %ebp
ret
.def _g; .scl 3; .type 32; .endef
265:264
08/01/29 13:01:03
>>263
使っているコンパイラでは結果が違うかもしれない。そういう環境で、且つ、実際に
そのレベルの高速化が必要ならビット AND への置き換えもありうる。ただしその場合は
しっかりコメントで実験結果に基づくコードだと添えておく必要があるだろうね。
266:デフォルトの名無しさん
08/01/29 13:11:04
なるほど、ありがとうございます。
267:デフォルトの名無しさん
08/01/30 20:35:23
実装が長くても1度しか呼ばれない関数って、普通最適化でインライン展開されますよね?
268:デフォルトの名無しさん
08/01/30 20:41:11
試してみれば?
269:デフォルトの名無しさん
08/01/30 20:46:26
インライン展開されます
270:デフォルトの名無しさん
08/01/30 20:46:55
コンパイラによってはインライン関数がちゃんと展開できたか教えてくれるコンパイルオプションがあるよ
gccの話だけど
271:デフォルトの名無しさん
08/01/30 20:47:27
ごめんなさい忘れてください
272:デフォルトの名無しさん
08/01/31 13:23:04
同じ内容の関数を複数用意して使い分ける意味ってあるんでしょうか?
273:デフォルトの名無しさん
08/01/31 14:21:21
>>272
唐突に質問されても何を聞きたいのか判りませんが。
同じ内容でも型が違う場合はC++ではテンプレート関数で一つで済ませることもできますが、
Cではできません。その辺りの話でしょうか?
274:デフォルトの名無しさん
08/01/31 14:30:48
>>273
そうではなく、
void foo1(int hoge){};
void foo2(int hoge){};
void foo3(int hoge){};
中の処理も全く同一な関数です
オーバーロードだとかそういうのでも全くないです
275:デフォルトの名無しさん
08/01/31 14:35:21
>>274
別に意味なんてないと思うが。訳が分からん。
typedef void (*func_t)(int);
とやっておいて、どこかでfunc_tの変数を宣言してそれらを代入し、
fptr1 = foo1;
fptr2 = foo2;
if(fptr1 == fptr 2){ ... }else{ .. }
として、処理は同じだけど違うものとして動作させたいと言うくらいしか思いつかないな。
意味があるかないか、どちらにしろそのソースコードを書いた人に直接訊いてみれば良い。
276:デフォルトの名無しさん
08/01/31 14:38:01
ただのアホな作りなのか、後の仕変に対応するための措置なのか見極める必要はある。
現状で言えばまとめてしまって構わないとは思うが。
277:デフォルトの名無しさん
08/01/31 14:49:44
I キャッシュの関係で、そういうのを最適化のために使えるケースというのはあった。リンカスクリプトも直す必要があるが。
多分違うケースなんだろうけど。
278:デフォルトの名無しさん
08/01/31 19:56:47
>>272
目的があれば意味があるんじゃないの?
279:デフォルトの名無しさん
08/01/31 19:57:35
string::size と string::length は全く同じメソッドだな。
文字列としては length という言葉を使う方がしっくりくるが、
コンテナとしての要件を満たすには size がないと困る。
なら両方作っちゃえって感じなんだろう。
こういう例ならありうると思う。
280:デフォルトの名無しさん
08/02/02 20:08:27
ファイルやフォルダをコピーしたり消したり作ったり、.NETで言うFileInfoクラスやDirectoryInfoクラスを
自分で実装するのは.NETに頼らなくて済む、以外のメリットないのかなぁ・・
このまま行くと.net病になりそうだ・・・
どうすりゃ効率いいかなぁ・・
281:デフォルトの名無しさん
08/02/02 20:18:24
既存のクラス使う方が仕事の効率は良さそうだな。
282:デフォルトの名無しさん
08/02/02 20:18:25
微妙に誤爆・・だけど平気かぎりぎり・・・いやごめんなさい
283:デフォルトの名無しさん
08/02/02 20:20:15
うひょー、れすがついちゃってた
>>281
Windows専用なら.NET全然良いかな、と思う
でも趣味でやってる分には微妙に素直に割り切れないというかなんというか
284:デフォルトの名無しさん
08/02/02 20:24:31
というかそのFileInfoクラスだけならともかくさ、他にも色々必要だろ
言い過ぎの誇張表現になるけどそのすべてにおいてMS開発陣の書いたコード以上のものを書けるのかってことになる
つまり.NETを1箇所以上で使うなら出来得る限り.NETで実装を
285:デフォルトの名無しさん
08/02/02 20:25:36
効率ってのが速度を表すなら、全ての.NETコードは効率が悪いことになる。
286:デフォルトの名無しさん
08/02/02 20:26:18
個人でやる分には安心感はあるけどねえ
287:デフォルトの名無しさん
08/02/02 20:26:47
>>279
lengthはsizeを呼ぶだけとかってなら、アリだね。
極力重複コードは避けるべき。
288:デフォルトの名無しさん
08/02/02 20:28:45
うあー、こんなんにレスつけてくれてありがとうございます
>>284
コードの数割は.NETのを利用したもので、主要な処理の部分だけちょっとがんばって
頼らず書こうかなと思ってたんだけどそのままにしときます
289:デフォルトの名無しさん
08/02/02 21:15:21
まあ.NETのあるクラスのすべてのメソッドをフル活用する状況ならいんじゃないかねえ
290:デフォルトの名無しさん
08/02/03 02:50:44
>>287
重複コードは inline 関数のおかげで簡単に避けられるね。
Ruby とか同じ動作の別名関数が用意されてる事が多い。
A という言語では a という名前で、
B という言語では b という名前な関数を Ruby に作る時には、
a と b の両方の名前を採用しちゃえ、みたいな。
291:デフォルトの名無しさん
08/02/03 03:04:15
そういえばC++には識別子のalias機能がないんだね。
292:デフォルトの名無しさん
08/02/03 03:12:28
で、でふ
293:デフォルトの名無しさん
08/02/03 03:13:17
変数は参照で、
関数はインライン関数で、
型は typedef で、
名前空間は namespace a = b; で、
クラステンプレートは継承でそれぞれ可能ではある。
ただ、インライン関数使うのと、
クラステンプレートを継承するのとは、
結構面倒臭い。
294:デフォルトの名無しさん
08/02/03 03:16:11
このスレ地味に常駐多くないかい
295:デフォルトの名無しさん
08/02/03 12:27:22
C++0xであるかも知れないが、テンプレートのエイリアスは作れないよな。
typedef std::vector my_vector;
みたいなの。>>293にも書いてある継承は可能ってレベルではない。
コンストラクタやらオペレータやら全部知っていて、尚かつ書かないといけない。
296:デフォルトの名無しさん
08/02/03 12:33:01
オペレータは必要ないと思う。
コンストラクタは作らないとダメだけど。
297:デフォルトの名無しさん
08/02/03 13:55:01
>>296これで例として成立してるか自身無いけど。
継承しちゃうとoperatorの返す型と継承した型が異なっちゃうからうまくいかない。
struct c {
int v;
c operator+(int n) {
c t;
t.v = v + n;
return t;
}
};
struct d:public c {};
main() {
d e, f;
f + 1; // OK
e = f; // OK
e = f + 1; // Error
}
298:デフォルトの名無しさん
08/02/03 14:01:54
>>297
ああ、なるほど。
というか、色んな状況を考えると継承では不完全なのか。
299:デフォルトの名無しさん
08/02/03 16:10:51
if(hoge.piyo == hogehoge.piyo)
hoge.piyo = hoge.piyo & ~sym.att;
こんなのはこれ以上どうにもなりませんよね?
300:デフォルトの名無しさん
08/02/03 18:04:15
分岐は無くせるけどね。
hoge.piyo = ~(sym.att & -(hoge.piyo==hogehoge.piyo) & hoge.piyo;
x86でPentiumPro以降に限定するなら
hoge.piyo = ~(hoge.piyo == hogehoge.piyo ? sym.att : 0) & hoge.piyo;
はCMOVになる可能性がある。
SSEで書けば次のようにも出来る。
// hoge.piyo = ~(sym.att & -(hoge.piyo==hogehoge.piyo) & hoge.piyo;
hige.piyo = _mm_andnot_ps(_mm_and_ps(sym.att, _mm_cmpeq_ps(hoge.piyo, hogehoge.piyo)), hoge.piyo);
ただSIMD以外は保守性が悪くなるだけであんま効果無いと思う。
実測した方がいい。
301:デフォルトの名無しさん
08/02/03 20:29:28
>>300
なるほど・・-ってのを初めてみたんで調べてきます、ありがとうございます
302:デフォルトの名無しさん
08/02/03 23:44:47
ANSI Cの仕様ではA==Bが真なら1になるから-1(全ビットON)にしてマスク作ってるだけだよ。
x86なら分岐せずにSETcc + NEGにコンパイルされるはず。
303:デフォルトの名無しさん
08/02/04 00:57:10
偉そうな割には右括弧が足りないぞ。
304:デフォルトの名無しさん
08/02/04 01:00:29
どの道やってること同じではないのか
305:デフォルトの名無しさん
08/02/04 13:36:34
まぁ、>299程度ならコンパイラに任せて実測してみてからだな。
CMOVになったところで大した差は出ないだろ。
306:デフォルトの名無しさん
08/02/04 13:37:59
Windows環境でのファイルなんかのコピーを大きくする手段ってないですよね・・
どのみちOSの機能頼りなわけだから
307:デフォルトの名無しさん
08/02/04 13:39:36
コピーしたつもりがおっきくなっちゃうのかー。そりゃねーな。
308:デフォルトの名無しさん
08/02/04 13:41:01
すんません、ガチで寝ぼけてる
早くする、ですほんとごめんなさいごめんなさいごえmんあい
309:デフォルトの名無しさん
08/02/04 13:43:14
早くする手段ならいくらでもあるだろ。
速いかどうかは知らんが。
310:デフォルトの名無しさん
08/02/04 13:48:24
ストライピング
コードレベルの最適化とは無縁だが。
311:デフォルトの名無しさん
08/02/04 13:54:21
高速化っていうんだから速くか
ストライピング、調べてきました
それだと送り先が2箇所なのかな・・・
コピー元も先も1箇所なんです
というかコードレベルって話じゃないですよね、把握しました
312:デフォルトの名無しさん
08/02/04 13:55:51
単純にバッファをいじるとか
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet
/Control/Session Manager/Memory Management
ここの数値を
というか普通こんなことしねえよな・・
313:デフォルトの名無しさん
08/02/04 13:58:42
>>311
実際問題、ファイルアクセスの速度はデバイス側の事情で決まってしまう。
と言うことで、単純に速くする方法はない。
寧ろ、本当にファイルコピーの時間が問題なのか、例えばレスポンスが問題なのか、検討した方がいい。
314:312
08/02/04 13:59:50
うちの環境だと10Mにしてるけどよく考えたら馬鹿すぎる方法だ
確か再起動必要だった気がするし
315:311
08/02/04 14:12:46
>>313
最近、.NETFrameworkというものを触ってみまして
色々試してみようとコンソールなんですがファイルをコピー(バックアップ?)する
ものを作ってみたんですが、そこでコピー自体速くならないかなあと思った次第です
>>312>>314
再起動必要じゃあれですね・・・
Win32APIとかってのもWindowsの機能を使うやつだって聞いたんで
それでファイルのコピーするとこを実装すれば速いんだろうか
316:デフォルトの名無しさん
08/02/04 14:20:28
>>315
先ず、.Netって時点でスレ違い。
次に、ファイルコピー自体の速度はデバイス依存だ。
.Netでファイルコピーしていて遅いと思うのなら、コードレベルの最適化ではなく.Netの使い方の問題だ。
317:デフォルトの名無しさん
08/02/04 14:23:52
C/C++でファイルコピーなんてファイル開いて読み取って書き込むの繰り返しなんだからさ
たぶん.NETでもAPIでも使った方が良い
ということでもうそれで完成でいいじゃない
318:デフォルトの名無しさん
08/02/04 22:14:23
>>311
Windows 限定なら FastCopy.exe のソースとか見ればいいんじゃないか。
319:デフォルトの名無しさん
08/02/04 22:28:22
オープンソースとか見ると趣味人でもない限りC/C++やWinAPIを使うのってことがどういうことかわかっちゃうよな
320:デフォルトの名無しさん
08/02/04 23:24:12
俺は、お前の言ってることがどういうことかわからん。
321:デフォルトの名無しさん
08/02/04 23:30:10
開発効率と現状溢れかえってるPCのスペックの話だろうか
まあ例外は確かに往々にあるけど例外は圧倒的にマイノリティ
うちも業務じゃC/C++なんて使わないわ
322:デフォルトの名無しさん
08/02/05 00:05:18
何言ってんだこいつ。
Webでもやってろ。
323:デフォルトの名無しさん
08/02/05 00:09:41
webは全然分類違うだろ、どこのアマグラマだよ
324:デフォルトの名無しさん
08/02/05 00:10:33
業務でC++主流だと思ってるのか・・
325:デフォルトの名無しさん
08/02/05 00:14:07
マジョリティマイノリティでわけちゃうとなぁ
まあ業務になると大抵どっちかだけ向いてればいいんだが
326:デフォルトの名無しさん
08/02/05 00:46:26
スレチ自重
327:デフォルトの名無しさん
08/02/06 20:32:36
ここに適当なコード張ってみんなで最適化とか考えたけど適当な長さのコードが見当たらなくて10分で諦めた
328:デフォルトの名無しさん
08/02/07 16:30:40
AMD向けの最適化に関するマニュアルはAMDのホームページにありますが、インテル用のはどこかでダウンロードできなうのでしょうか?
329:デフォルトの名無しさん
08/02/07 16:42:36
>>328
URLリンク(www.intel.co.jp)
330:デフォルトの名無しさん
08/02/09 12:32:52
>>328
URLリンク(www.agner.org)
331:デフォルトの名無しさん
08/02/11 03:01:18
おいお前ら、俺のこいつをみてどう思う?
class Vector3
{
public:
union
{
struct {float x, y, z;}
float data[3];
};
Vector3() {}
Vector3(float ix, float iy, float iz)
{
x = ix;
y = iy;
z = iz;
}
};
inline Vector3 operator+(const Vector3 & va, const Vector3 & vb)
{
return Vector3(va.x + vb.x, va.y + vb.y, va.z + vb.z);
}
ベクトル化されるかな
332:デフォルトの名無しさん
08/02/11 03:16:06
人に読んでもらうんならもうちょっとマシなコードを書いて欲しい所
333:デフォルトの名無しさん
08/02/11 03:17:37
横レスだが、別に普通じゃねえかw
334:デフォルトの名無しさん
08/02/11 03:50:50
全角スペースでいいからインデントをだな
335:デフォルトの名無しさん
08/02/11 03:51:35
コードがマシかどうかとは関係ないじゃん
336:デフォルトの名無しさん
08/02/11 03:52:06
>>332
「もうちょっとマシなコード」をkwsk
337:デフォルトの名無しさん
08/02/11 03:52:14
>>334だけど>>332じゃないです
338:デフォルトの名無しさん
08/02/11 03:52:45
ここで一つ自演を見付けると
339:331
08/02/11 04:00:14
分かった、インデントが無いのは謝る
コンパイラ通してないのも謝る
ただ俺は…ベクトル化について語って欲しかっただけなんだ…
340:デフォルトの名無しさん
08/02/11 04:03:30
コンパイルしてみりゃいいじゃん。
341:デフォルトの名無しさん
08/02/11 04:30:20
>>336
・classじゃなくて別にstructでいいんじゃ?
・無名共同体内無名構造体の後のセミコロンがない
・デフォルトコンストラクタ邪魔
・メンバ初期化子を使って欲しい そして出来れば引数もconst type&で受け取った方が
・演算子オーバーロードを行う関数の引数名はrhs, lhsにするのが普通
342:デフォルトの名無しさん
08/02/11 05:04:44
>>341
・classじゃなくて別にstructでいいんじゃ?
俺は変数だけならstruct、関数あるならclass使ってるが
・無名共同体内無名構造体の後のセミコロンがない
struct {float x, y, z;} ←これか。スマン
・デフォルトコンストラクタ邪魔
コンパイラによっては0で初期化される・・・っていう記憶があるから、
不定値のままでいいから一応書いた
メンバ初期化子を使って欲しい そして出来れば引数もconst type&で受け取った方が
うぉ?!全くその通りだw
Vector3(const float & ix, const float & iy, const float & iz)
: x(ix), y(iy), z(iz)
{}
これでおk?
・演算子オーバーロードを行う関数の引数名はrhs, lhsにするのが普通
知らんかった
レスありがとう
343:デフォルトの名無しさん
08/02/11 05:22:15
忘れるところだった。俺はベクt(ryについて聞いてたんだ
return Vector3(va.x + vb.x, va.y + vb.y, va.z + vb.z);
こいつはベクトル化されるのか?
それとも、
Vector3 v;
for (int i = 0; i < 3; i++) {v.data[i] = lhs.data[i] + rhs.data[i];}
return v;
とか書かないとダメかな
まぁコンパイラ依存な訳だが、どこまで美味く最適化してくれるか知りたいんだ
344:デフォルトの名無しさん
08/02/11 05:27:03
そこだけ見てもベクタ化されるかどうかは不明。
ってことで、クラスの作りだけ見ると、unionにする理由が判らん。
配列のようにも構造体のようにも使いたいのならそういうアクセッサを用意すればいいだけだから、
そもそもデータメンバを公開する理由が判らん。
あーそれから、floatを引き数とするコンストラクタなら参照にしなくて充分。
345:デフォルトの名無しさん
08/02/11 05:29:19
>>343
だから、コンパイラが何か、どんな使い方をするかなども書かれていないのにベクタ化されるかは不明だってば。
わざわざforループにしなくても、ベクタ化できるコンパイラならベクタ化すべきときにはしてくれるだろうよ。
346:デフォルトの名無しさん
08/02/11 05:48:14
これは3次元ベクトルのクラス。できる限りの高速化が望まれる
xyz公開してるのはGetX()とか作ったり使ったりするのが面倒くさいからだ
コンパイラはVisual Stdio 2005のやつ
347:デフォルトの名無しさん
08/02/11 06:15:07
「できる限りの高速化」を望みつつ、条件も出さずに実測もしないで、
挙句の果てに「面倒くさい」って、阿呆ですか?
348:デフォルトの名無しさん
08/02/11 07:07:04
>>347
俺が求めてるのは実測とかじゃなくて、最適化についての経験談なんだが
こうした方がベクトル化され易い、とか…
あと、
void Vector3::GetX() const {return x;}
void Vector3::GetY() const {return y;}
void Vector3::GetZ() const {return z;}
とか実装しろと?
最適化、いや高速化に関係するのか?
349:デフォルトの名無しさん
08/02/11 07:42:43
>>348
だから、いろんなサンプル作って実測してみろって。
クラスを作るのなら効率よく組めて且つ速いものも狙うのは当然だろうし、
そうでないなら速度重視でがりがり書くことになるからクラスなんて作る意味がないって。
要は、やることが半端なの。
350:デフォルトの名無しさん
08/02/11 10:17:11
float を参照渡しする意味はあるのか?
351:デフォルトの名無しさん
08/02/11 10:21:53
>>349
自己矛盾乙
352:デフォルトの名無しさん
08/02/11 10:28:39
むしろだめだろう、リテラルわたせないじゃないか
353:デフォルトの名無しさん
08/02/11 10:36:13
一時オブジェクトが生成されるから問題ない。
354:デフォルトの名無しさん
08/02/11 10:37:31
インライン化されるだろうから多分変わりはないだろうが、
積極的に参照にする理由は無いな。
355:デフォルトの名無しさん
08/02/11 10:39:02
そうでしたかごめんなさい
356:デフォルトの名無しさん
08/02/11 10:43:56
>>351
どこが自己矛盾?
357:デフォルトの名無しさん
08/02/11 11:55:47
他人に訊く暇があったらまずやってみろ!
それで自分の力だけではどうにもならない事が起きた時初めて他人を頼る
でないといつまでたっても他人に頼る癖が抜けないぞ
358:デフォルトの名無しさん
08/02/11 11:56:22
インライン化される事を前提としているならconst参照渡しは問題ないというかコンパイラの助けにある程度なるだろうけど、
確かに中途半端に長い関数で1ワードごときの変数を参照にする必要は無い。
359:デフォルトの名無しさん
08/02/12 02:45:14
>>357
ここは相談の場でなくて語り合う場だが?
360:デフォルトの名無しさん
08/02/12 04:43:20
void float Func(const float &f)
{
return (f + f - f) * f / f;
}
イコール
void float Func(const float *f)
{
return (*f + *f - *f) * (*f) / *f
}
だと思ってた。それとも
void float Func(const float *f)
{
float g = f;
return (g + g - g) * g / g;
}
こうか?参照渡しって内部的にどういう処理が行われてるの
361:デフォルトの名無しさん
08/02/12 08:03:41
>>360
最適化されると、後2者の区別はなくなりますが。
# void float とかfloat g = f は兎も角
362:デフォルトの名無しさん
08/02/12 11:12:40
>>360
最適化されると、内部的に変数の所在を渡すよりも変数の値をそのまま渡した方が速度が出るので
void float Func(const float f)
{
return (f + f - f) * f / f;
}
になる。
363:デフォルトの名無しさん
08/02/12 11:26:12
適当にコピペして解説したんだけど
>void float
まさかこんな風に書いてあったなんて
364:デフォルトの名無しさん
08/02/12 11:27:45
>>362
最早意味不明だし。インライン展開されない限り、参照やポインタ渡しが値渡しになることは有り得ません。
# インライン展開されたらされたで、Func()自体が(その呼び出しについては)消えてなくなるだろうけど。
365:デフォルトの名無しさん
08/02/12 11:41:48
>>364
不動小数点数の演算って、足して引いて 0 とか、かけて割って 1 とか、畳んでいいんだっけ?
366:デフォルトの名無しさん
08/02/12 11:44:28
>>365
実際に最適化されるときに、引き数が明らかなら可能。
そういう意味では、>364は不正解。
367:364
08/02/12 12:05:54
>実際に最適化されるときに、引き数が明らかなら可能。
あー失礼しました。
gccでの確認ですが、確かにFunc(1.2f)とかは消えてなくなるけど
Func(atof(argv[1]))とかだとちゃんと四則演算してますね。
--
call __strtod_internal
fstps -4(%ebp)
movss -4(%ebp), %xmm3
movss %xmm3, %xmm1
addss %xmm3, %xmm1
subss %xmm3, %xmm1
mulss %xmm3, %xmm1
divss %xmm3, %xmm1
subl $8, %esp
cvtss2sd %xmm1, %xmm0
movsd %xmm0, (%esp)
368:デフォルトの名無しさん
08/02/14 07:30:06
C/C++でGUIを実装する場合、どういった手段が適当でしょうか?(Windows環境)
色々調べてみたところ
・実際の職業プログラマさんなんかはC#やVB.NETみたいなのを使う
・WinAPIを直接、みたいなことは趣味でやる人が使う
(山を登るのに、ロープウェイを使うのが賢いが趣味で山登りを楽しむ人がいるみたいな意味で)
で、実際人に聞くと今度はMFCという意見が出てきました
調べるとWinAPIを糖衣したようなもののように感じたものの情報がすごく少ない
と、こんな感じでして、どっちに進むべきか悩んでいます
やりたいのはどっちだ、というのは手段と目的がryってやつでGUIの実装の手段をどうしたものか、という質問です
C#/VB.NETというものも一応考慮のうちに入れておきたいです
(GUIの実装はC/C++の枠を超えればそれがベターだから、という意見も考慮したいからです)
それではよろしくお願いします
369:デフォルトの名無しさん
08/02/14 07:56:45
スレタイ読め
370:360
08/02/14 09:34:39
スマン、遅レスだがvoidは間違いだ
floatもマズかったかな
double Func(const double &d)
{
return (d + d - d) * d / d;
}
こいつはコンパイルされた後ってどうなるんだ?
アセンブリ知らないから、とりあえずCの文法的に書いてみるけど
double Func(double d)
{
return (d + d - d) * d / d;
}
になるのか。それとも
double Func(double *d)
{
return (*d + *d - *d) * (*d) / *d;
}
になるのか。まさか後者みたいなコード吐かないよね
もちFunc関数自体が省略されない場合で
371:デフォルトの名無しさん
08/02/14 09:45:00
>>370
アセンブリ知らないという見方なら C の規格上の実行モデルで考えることになり、
その場合にはそれら2つは引数が値渡しである点を除いてほぼ等価。
違いを知りたければアセンブリを見るしかないでしょ。
372:デフォルトの名無しさん
08/02/14 09:46:13
コンパイルして逆アセンブルしてみればいいんじゃないの?
373:368
08/02/14 10:34:16
すんませんごばく
374:デフォルトの名無しさん
08/02/14 11:38:12
>>370
参照で書かれた関数は、ポインタで書かれた関数と同じコードを吐くよ。
その例では、後者と同じと言うことになる。
勿論、後者自体がdouble Func(double * d) {double tmp = * d; return (tmp + tmp - tmp) * tmp / tmp;}
と殆んど同じコードを吐くという前堤でね。
375:デフォルトの名無しさん
08/02/14 12:36:36
ちょっとコンパイルしてみた。
--
double func(double const d) {return (d + d - d) * d / d;}
double func(double const & d) {return (d + d - d) * d / d;}
double func(double const * d) {return (* d + * d - * d) * * d / * d;}
double func(double const * d) {double tmp = * d; return (tmp + tmp - tmp) * tmp / tmp;}
-- 以下適当に行を圧縮
_Z4funcd:
movapd %xmm0, %xmm1 addsd %xmm0, %xmm1
subsd %xmm0, %xmm1 mulsd %xmm0, %xmm1
divsd %xmm0, %xmm1 movapd %xmm1, %xmm0
ret
_Z4funcRKd:
movsd (%rdi), %xmm1 movapd %xmm1, %xmm0
addsd %xmm1, %xmm0 subsd %xmm1, %xmm0
mulsd %xmm1, %xmm0 divsd %xmm1, %xmm0
ret
_Z4funcPKd:
movsd (%rdi), %xmm1 movapd %xmm1, %xmm0
addsd %xmm1, %xmm0 subsd %xmm1, %xmm0
mulsd %xmm1, %xmm0 divsd %xmm1, %xmm0
ret
_Z4funcPKd:
movsd (%rdi), %xmm1 movapd %xmm1, %xmm0
addsd %xmm1, %xmm0 subsd %xmm1, %xmm0
mulsd %xmm1, %xmm0 divsd %xmm1, %xmm0
ret
376:デフォルトの名無しさん
08/02/14 14:55:14
>>375
VC++2003で最適化オプションを全て有効にして、その4つの関数を定義して
連続で呼び出してみたら、インライン展開されて計算は1回だけで結果を
4回コピーするだけのコードになった。完全に同一とみなされてるね。
あと、インライン展開されてないコードではSSEを使っているけど、展開された
部分ではSSEは使ってなかったな。
377:360
08/02/16 01:27:08
俺の環境(VS2005SE)で速度重視ならこんな感じ
展開はされてない
func1:
fld qword ptr [esp+4] fld st(0)
fadd st,st(1) fsub st,st(1)
fmul st,st(1) fdivrp st(1),st
ret
func2:
fld qword ptr [eax] fadd st(0),st
fsub qword ptr [eax] fmul qword ptr [eax]
fdiv qword ptr [eax] ret
func3:
fld qword ptr [eax] fadd st(0),st
fsub qword ptr [eax] fmul qword ptr [eax]
fdiv qword ptr [eax] ret
func4:
fld qword ptr [eax] fld st(0)
fadd st,st(1) fsub st,st(1)
fmul st,st(1) fdivrp st(1),st
ret
あれ、これってSSE使われてないよね。なんで?
378:デフォルトの名無しさん
08/02/16 23:17:22
>>370
参照はポインタで渡されるので、関数を呼び出す場合は後者の関数が生成される。
インライン展開されるばあいは、最適化されてポインタが使われない前者と同等になるよ。
>>376
2005proではインライン展開もSSE2になってた。
>>377
SSE2のオプションは確認した?
379:デフォルトの名無しさん
08/02/17 09:22:53
>>378サンクス。オプション忘れてたw
インライン展開されているものは全て同じコード吐いてるっぽい
されていないものはこんな感じ
double func1(double const d) {return (d + d - d) * d / d;}
004018A0 movapd xmm0,xmm1
004018A4 addsd xmm0,xmm1
004018A8 subsd xmm0,xmm1
004018AC mulsd xmm0,xmm1
004018B0 divsd xmm0,xmm1
004018B4 ret
double func2(double const & d) {return (d + d - d) * d / d;}
double func3(double const * d) {return (* d + * d - * d) * * d / * d;}
double func4(double const * d) {double tmp = * d; return (tmp + tmp - tmp) * tmp / tmp;}
00401880 movsd xmm1,mmword ptr [eax]
00401884 movapd xmm0,xmm1
00401888 addsd xmm0,xmm1
0040188C subsd xmm0,xmm1
00401890 mulsd xmm0,xmm1
00401894 divsd xmm0,xmm1
00401898 ret
func1の方が短い事にちょっぴり驚いた。引数でdoubleそのまま使うのも有りって事か?
380:デフォルトの名無しさん
08/02/17 11:18:29
このスレに来て学んだことは「とりあえず素直に書いておけ」
381:デフォルトの名無しさん
08/02/17 12:34:23
結局、最適化器を書いてるのは人間だから、
「彼らが想定する人間であること」
が大事になってくるわな。
382:デフォルトの名無しさん
08/02/17 18:45:37
double を参照渡しはまずせんわな。
383:デフォルトの名無しさん
08/02/17 20:55:13
たしかに直接にdoubleを参照渡しにすることは無いけど、テンプレートを使うときに引数を参照渡しにすることはよくある。
その結果、doubleを参照渡しにしてしまうことも多々ある。インライン展開なら参照渡しもしっかり最適化されるので助かる。コンパイラ屋さんに感謝だな。
384:デフォルトの名無しさん
08/02/17 21:59:07
値渡し用の型を取得するためのテンプレート使うといいよ。
385:デフォルトの名無しさん
08/02/17 21:59:30
値渡し用の型、じゃねえや。
そういった引数用の型、だ。
386:デフォルトの名無しさん
08/02/17 22:01:08
テンプレートだと、問答無用に値渡ししないか?
と思ったが、bindとかfunctionとか参照渡しだったな。
387:デフォルトの名無しさん
08/02/17 22:04:48
特定の基本型のみ値渡しにし、
他の型は全部 const 参照にするってやつ。
要するに boost::call_traits<T>::param_type 。
388:デフォルトの名無しさん
08/02/17 23:13:07
凄いことができるんだな。テンプレートって奥が深いな
389:デフォルトの名無しさん
08/02/17 23:15:22
つかフツウやるやろ
390:デフォルトの名無しさん
08/02/17 23:16:53
まあ実装はかなり泥臭いがな。
基本的に const 参照にして、基本型全部で特殊化。
実際にはもうちょっと階層的に作ってあるけど、
基本的にはそんなとこ。
391:デフォルトの名無しさん
08/02/18 03:33:06
分かりやすいのが一番だと思ってる。でも必要な所はあるわけですよ
・・・このスレに何しに来たっけ
これをどうするか聞きに来たんだっけかw
//----------
class Vector4
{
public:
float x, y, z, w;
Vector4(float ix, float iy, float iz, float iw)
: x(ix), y(iy), z(iz), w(iw)
{}
};
void Add(Vector4 * pO, const Vector4 & iA, const Vector4 & iB)
{
pO->x = iA.x + iB.x;
pO->y = iA.y + iB.y;
pO->z = iA.z + iB.z;
pO->w = iA.w + iB.w;
}
//----------
ベクトル和を計算するAdd関数がある訳だが、とにかく速度が欲しい。
SSEのパックド単精度実数関連の命令(ADDPSとか)使えば早くなるはずだと
というか、最適化で勝手にやってくれると思っていたんだが、パックド使ってるようには見えない
まさか、この程度なら使わない方が早いのか・・・
おまいらならどうコーディングする?
完全にぶりかえしですまん
392:デフォルトの名無しさん
08/02/18 04:02:10
コンパイラが場合によって速いほうを選べるように inline にする。
必要な箇所があれば intrinsic でもアセンブラでも使う。
393:ヽ・´∀`・,,)っ━━━━━━┓
08/02/18 04:26:20
残念だがそれをaddps1個に翻訳できるほど現時点でのコンパイラは賢くない。だからこそのIntrinsicsなわけで。
394:ヽ・´∀`・,,)っ━━━━━━┓
08/02/18 06:37:36
//----------
#include <dvec.h>
class Vector4 : public F32vec4
{
public:
Vector4(float ix, float iy, float iz, float iw)
: vec(ix, iy, iz, iw)
{}
};
void Add(Vector4 * pO, const Vector4 & iA, const Vector4 & iB)
{
*pO = iA + iB;
}
この程度だとラップする意味が無い
395:ヽ・´∀`・,,)っ━━━━━━┓
08/02/18 06:40:31
Intel C++ or VC++なら
#include <fvec.h>
でF32vec4を使う。
テキトーにラップしてよし。
あと、インライン化しないとあんまり効果ないよ。
実関数化するとコールのオーバーヘッドに食われる
396:ヽ・´∀`・,,)っ━━━━━━┓
08/02/18 06:41:40
class Vector4 : public F32vec4
{
public:
Vector4(float ix, float iy, float iz, float iw)
: F32vec4(ix, iy, iz, iw)
{}
};
に訂正
397:デフォルトの名無しさん
08/02/18 08:29:40
ダンゴさんの連投でスレが活気付いたな
398:デフォルトの名無しさん
08/02/18 08:38:46
活気づいたっていうのかよこれは
399:デフォルトの名無しさん
08/02/18 10:24:21
1人だけで盛り上がっていては活気付いたとはいえない。
実際に活気付くのは397からだから397の話題振りで活気付いたということにしないと。
400:デフォルトの名無しさん
08/02/18 12:34:36
>>391
こうならばどうか?
//----------
class Vector4
{
private:
float x, y, z, w;
public:
Vector4(float ix, float iy, float iz, float iw)
: x(ix), y(iy), z(iz), w(iw)
{}
void Add(Vector4 * pO, const Vector4 & iA, const Vector4 & iB)
{
pO->x = iA.x + iB.x;
pO->y = iA.y + iB.y;
pO->z = iA.z + iB.z;
pO->w = iA.w + iB.w;
}
//或いは
void Add(Vector4& pO, const Vector4 & iA, const Vector4 & iB)
{
pO.x = iA.x + iB.x;
pO.y = iA.y + iB.y;
pO.z = iA.z + iB.z;
pO.w = iA.w + iB.w;
}
401:デフォルトの名無しさん
08/02/18 12:36:08
>>400
最後の行に括弧が抜けてた。
};
402:ヽ・´∀`・,,)っ¬
08/02/18 15:42:20
駄目。それでもスカラにしかならない。
addpsに展開されることが目的なら、配列にして
for(int i=0; i<4; i++) vD[i] = vA[i] + vB[i];
全要素に同じ操作をしてますよってヒントにはループが一番効果的。
手動アンロールしちゃうと効果ない。
403:デフォルトの名無しさん
08/02/18 15:57:21
それバールだったのか。釣竿だと思ってたぜ。
404:デフォルトの名無しさん
08/02/18 16:10:23
内部をバラの変数にしても配列にしても外からはわからない。
これぞクラスで隠蔽する良さだな。
405:デフォルトの名無しさん
08/02/19 03:27:11
遅レスすまん
f・・・vec.h・・・?こんなの知らなかったよ。
fvec.h は実数、dvec. h は整数の CPU 拡張機能を用いた演算関連のヘッダー、でいいのかな
class Vector4 : public F32vec4
{
public:
Vector4() {}
Vector4(float ix, float iy, float iz, float iw) : F32vec4(ix, iy, iz, iw) {}
Vector4 & operator =(const F32vec4 & rhs) {*this = rhs; return *this;}
};
inline void Add(Vector4 * pO, Vector4 & iA, Vector4 & iB)
{
*pO = iA + iB;
}
inline void Normalize(Vector4 * pO, const Vector4 & i)
{
F32vec4 v2(i * i);
F32vec4 norm(sqrt(v2[0] + v2[1] + v2[2] + v2[3]));
*pO = i / norm;
}
正規化関数も作ってみた。俺の理解力だと今はこれが限界
Vector3 とかも作ってみたいが、float * 4 をパックにしなくちゃいかんから、float 1つ分余計にメモリ必要なんだな
fvec.h & dvec.h は xmmintrin.h をインクルードしてるが、直接使っても構わないかな
>>400
今まではそうしてた。あと、「};」が抜けてるからメンバ関数が inline か否か判らんぞ
追伸:Intrinsics の発音はイントリンシックスでおk?
406:デフォルトの名無しさん
08/02/19 04:22:14
>>405
>\in-?trin-zik, -?trin(t)-sik\
>URLリンク(cougar.eb.com)
よって、「イントリンジク」。
407:デフォルトの名無しさん
08/02/19 11:33:11
>>405
VC++なら
class Vector4
{
public:
union {
float d[4];
struct { float x, y, z, w; };
};
};
これでAddをforループにしたら、SSE使ってくれたよ。
408:デフォルトの名無しさん
08/02/19 12:23:05
class myvec
{
public:
union {
T array[N];
struct { T a, b, c, d, ... };
};
};
とする場合、特にTがマシンが扱う1Wordの倍数でないと
元々struct { T a, b, c, d, ... }; 部分の各要素の連続性が保証されてないからどう動くかが分からなくなる。
つまり T array[N] では T はきっちり詰め込まれているものの、 struct { ... }; は中で要素の間に空白のブロックが入る可能性がある。
ふじこふじこ
409:デフォルトの名無しさん
08/02/19 13:09:07
ごめん、407を訂正する。
SSE使っていることには使っているが
movss xmm4, DWORD PTR [eax-8]
addss xmm4, xmm0
movss DWORD PTR [eax-8], xmm4
こんなコード吐いてた。(要素数の数だけ繰り返し)
VC++2003ではベクトル化してくれるほど頭よくないようだ。
これでも普通にFPU使うよりは速いの?
410:デフォルトの名無しさん
08/02/19 21:57:23
>>407
クラスメンバの実体は
private:
float r[4];
にしといて、メンバ関数で
public:
float &x(){return r[0];};
const float &x()const{return r[0];};
などとするのがC++的。
411:デフォルトの名無しさん
08/02/19 21:58:16
>>409
x86-64はSSE使う方が速いし、FPUの利用は推奨されていない。
412:ヽ・´∀`・,,)っ━━━━━━┓
08/02/19 23:01:55
自動ベクトル化は何故かVC++ではやってくれないね。何年もなるのに未だに対応しない。
まあIntrinsicsを使うのがいいでしょう。
どのみち配列にしちゃうと仮に運よくベクトル化できてもメモリアクセスが必ず発生しちゃうので
性能落ちる。F32vec4かもしくは__m128iから派生するのがヨシ。
413:デフォルトの名無しさん
08/02/20 01:49:02
>>410
そういう仕様のベクトル演算クラスって少ないよ。C++でも
414:ヽ・´∀`・,,)っ━━━━━━┓
08/02/20 02:11:33
より汎用化したいならテンプレートにしてIntrinsicsベッタリな部分はtraitsで実装するとかいう手もあるわな
fvecやdvecはラッパークラスの実装サンプルだと思ってもいい。ちなみにSSE3~4には対応してない。
415:デフォルトの名無しさん
08/02/20 05:15:43
なるほど、実装サンプルね。じゃあdvecが参照してるヘッダを活用して
独自にラッパー作ってもいいわけだ
>どのみち配列にしちゃうと仮に運よくベクトル化できてもメモリアクセスが必ず発生しちゃうので
>性能落ちる
ここの意味がわかりませんぜ親分。うまくベクトル化できてもIntrinsics使ったコードには勝てないのか?
416:ヽ・´∀`・,,)っ━━━━━━┓
08/02/20 06:12:03
配列=かならずアドレスを持つ=レジスタ変数にできない。
いっぽうで__m128の実体はレジスタに割り当て可能。
レジスタ上に置いて演算を繰り返すような用途には、ロード・ストアは無駄。
417:デフォルトの名無しさん
08/02/20 11:56:09
なんでバールの人はそんなに詳しいの
418:デフォルトの名無しさん
08/02/20 12:25:31
>>416
> 配列=かならずアドレスを持つ=レジスタ変数にできない。
これってどんなコンパイラでもそうなっちゃうの?
419:デフォルトの名無しさん
08/02/20 12:53:19
>>418
最適化によってずっとレジスタに保持するケースもあるとは思うが、
それでも一応メモリ領域に置くだけは置くようだ。
420:デフォルトの名無しさん
08/02/20 12:59:55
>>419
へぇ。そんなこともあるんだ。
で、それは特定のコンパイラでの実験結果であて、規格上レジスタだけで
済ませることができない制約がある、というわけじゃないよね?
421:デフォルトの名無しさん
08/02/20 14:08:55
でもC++はregister変数のアドレスを取れちゃうから不思議。
422:デフォルトの名無しさん
08/02/20 14:23:19
ふと、メンバ変数も仮想関数もない空のクラスでも
アドレス取れないといけないからサイズ0にならないって話を
思い出した。
423:デフォルトの名無しさん
08/02/20 20:03:28
>>421
register はコンパイラへのヒントであって
必ずレジスタに割り付けする必要はないからな