[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 2chのread.cgiへ]
Update time : 05/18 20:43 / Filesize : 166 KB / Number-of Response : 785
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C、C++の最適化について語るスレ 2



1 名前:デフォルトの名無しさん mailto:sage [2007/04/29(日) 09:54:14 ]
コンパイラ性能、コンパイルオプション、コードの最適化などについて語りましょう。
主に速度面の最適化を中心としますが、サイズなどの最適化もどうぞ。
なお、OS、CPU、コンパイラなどは限定しません

前スレ

C、C++の最適化について語るスレ
pc11.2ch.net/test/read.cgi/tech/1084676298/


313 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 13:58:42 ]
>>311
実際問題、ファイルアクセスの速度はデバイス側の事情で決まってしまう。
と言うことで、単純に速くする方法はない。
寧ろ、本当にファイルコピーの時間が問題なのか、例えばレスポンスが問題なのか、検討した方がいい。

314 名前:312 mailto:sage [2008/02/04(月) 13:59:50 ]
うちの環境だと10Mにしてるけどよく考えたら馬鹿すぎる方法だ

確か再起動必要だった気がするし

315 名前:311 mailto:sage [2008/02/04(月) 14:12:46 ]
>>313
最近、.NETFrameworkというものを触ってみまして
色々試してみようとコンソールなんですがファイルをコピー(バックアップ?)する
ものを作ってみたんですが、そこでコピー自体速くならないかなあと思った次第です

>>312>>314
再起動必要じゃあれですね・・・
Win32APIとかってのもWindowsの機能を使うやつだって聞いたんで
それでファイルのコピーするとこを実装すれば速いんだろうか

316 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 14:20:28 ]
>>315
先ず、.Netって時点でスレ違い。
次に、ファイルコピー自体の速度はデバイス依存だ。
.Netでファイルコピーしていて遅いと思うのなら、コードレベルの最適化ではなく.Netの使い方の問題だ。

317 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 14:23:52 ]
C/C++でファイルコピーなんてファイル開いて読み取って書き込むの繰り返しなんだからさ
たぶん.NETでもAPIでも使った方が良い

ということでもうそれで完成でいいじゃない

318 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 22:14:23 ]
>>311
Windows 限定なら FastCopy.exe のソースとか見ればいいんじゃないか。

319 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 22:28:22 ]
オープンソースとか見ると趣味人でもない限りC/C++やWinAPIを使うのってことがどういうことかわかっちゃうよな

320 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 23:24:12 ]
俺は、お前の言ってることがどういうことかわからん。

321 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 23:30:10 ]
開発効率と現状溢れかえってるPCのスペックの話だろうか

まあ例外は確かに往々にあるけど例外は圧倒的にマイノリティ
うちも業務じゃC/C++なんて使わないわ



322 名前:デフォルトの名無しさん mailto:sage [2008/02/05(火) 00:05:18 ]
何言ってんだこいつ。
Webでもやってろ。

323 名前:デフォルトの名無しさん mailto:sage [2008/02/05(火) 00:09:41 ]
webは全然分類違うだろ、どこのアマグラマだよ

324 名前:デフォルトの名無しさん mailto:sage [2008/02/05(火) 00:10:33 ]
業務でC++主流だと思ってるのか・・

325 名前:デフォルトの名無しさん mailto:sage [2008/02/05(火) 00:14:07 ]
マジョリティマイノリティでわけちゃうとなぁ

まあ業務になると大抵どっちかだけ向いてればいいんだが

326 名前:デフォルトの名無しさん mailto:sage [2008/02/05(火) 00:46:26 ]
スレチ自重

327 名前:デフォルトの名無しさん mailto:sage [2008/02/06(水) 20:32:36 ]
ここに適当なコード張ってみんなで最適化とか考えたけど適当な長さのコードが見当たらなくて10分で諦めた

328 名前:デフォルトの名無しさん [2008/02/07(木) 16:30:40 ]
AMD向けの最適化に関するマニュアルはAMDのホームページにありますが、インテル用のはどこかでダウンロードできなうのでしょうか?

329 名前:デフォルトの名無しさん mailto:sage [2008/02/07(木) 16:42:36 ]
>>328
www.intel.co.jp/jp/download/index.htm

330 名前:デフォルトの名無しさん mailto:sage [2008/02/09(土) 12:32:52 ]
>>328
ttp://www.agner.org/optimize/

331 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:16:06 ]
人に読んでもらうんならもうちょっとマシなコードを書いて欲しい所

333 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:17:37 ]
横レスだが、別に普通じゃねえかw

334 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:50:50 ]
全角スペースでいいからインデントをだな

335 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:51:35 ]
コードがマシかどうかとは関係ないじゃん

336 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:52:06 ]
>>332
「もうちょっとマシなコード」をkwsk

337 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:52:14 ]
>>334だけど>>332じゃないです

338 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 03:52:45 ]
ここで一つ自演を見付けると

339 名前:331 mailto:sage [2008/02/11(月) 04:00:14 ]
分かった、インデントが無いのは謝る
コンパイラ通してないのも謝る

ただ俺は…ベクトル化について語って欲しかっただけなんだ…

340 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 04:03:30 ]
コンパイルしてみりゃいいじゃん。

341 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 04:30:20 ]
>>336
・classじゃなくて別にstructでいいんじゃ?
・無名共同体内無名構造体の後のセミコロンがない
・デフォルトコンストラクタ邪魔
・メンバ初期化子を使って欲しい そして出来れば引数もconst type&で受け取った方が
・演算子オーバーロードを行う関数の引数名はrhs, lhsにするのが普通



342 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 05:27:03 ]
そこだけ見てもベクタ化されるかどうかは不明。
ってことで、クラスの作りだけ見ると、unionにする理由が判らん。
配列のようにも構造体のようにも使いたいのならそういうアクセッサを用意すればいいだけだから、
そもそもデータメンバを公開する理由が判らん。
あーそれから、floatを引き数とするコンストラクタなら参照にしなくて充分。

345 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 05:29:19 ]
>>343
だから、コンパイラが何か、どんな使い方をするかなども書かれていないのにベクタ化されるかは不明だってば。
わざわざforループにしなくても、ベクタ化できるコンパイラならベクタ化すべきときにはしてくれるだろうよ。

346 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 05:48:14 ]
これは3次元ベクトルのクラス。できる限りの高速化が望まれる
xyz公開してるのはGetX()とか作ったり使ったりするのが面倒くさいからだ
コンパイラはVisual Stdio 2005のやつ

347 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 06:15:07 ]
「できる限りの高速化」を望みつつ、条件も出さずに実測もしないで、
挙句の果てに「面倒くさい」って、阿呆ですか?

348 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 07:42:43 ]
>>348
だから、いろんなサンプル作って実測してみろって。
クラスを作るのなら効率よく組めて且つ速いものも狙うのは当然だろうし、
そうでないなら速度重視でがりがり書くことになるからクラスなんて作る意味がないって。

要は、やることが半端なの。

350 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:17:11 ]
float を参照渡しする意味はあるのか?

351 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:21:53 ]
>>349
自己矛盾乙



352 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:28:39 ]
むしろだめだろう、リテラルわたせないじゃないか

353 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:36:13 ]
一時オブジェクトが生成されるから問題ない。

354 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:37:31 ]
インライン化されるだろうから多分変わりはないだろうが、
積極的に参照にする理由は無いな。

355 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:39:02 ]
そうでしたかごめんなさい

356 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 10:43:56 ]
>>351
どこが自己矛盾?

357 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 11:55:47 ]
他人に訊く暇があったらまずやってみろ!
それで自分の力だけではどうにもならない事が起きた時初めて他人を頼る
でないといつまでたっても他人に頼る癖が抜けないぞ

358 名前:デフォルトの名無しさん mailto:sage [2008/02/11(月) 11:56:22 ]
インライン化される事を前提としているならconst参照渡しは問題ないというかコンパイラの助けにある程度なるだろうけど、
確かに中途半端に長い関数で1ワードごときの変数を参照にする必要は無い。

359 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 02:45:14 ]
>>357
ここは相談の場でなくて語り合う場だが?

360 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 08:03:41 ]
>>360
最適化されると、後2者の区別はなくなりますが。
# void float とかfloat g = f は兎も角



362 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 11:12:40 ]
>>360
最適化されると、内部的に変数の所在を渡すよりも変数の値をそのまま渡した方が速度が出るので

void float Func(const float f)
{
 return (f + f - f) * f / f;
}

になる。

363 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 11:26:12 ]
適当にコピペして解説したんだけど
>void float
まさかこんな風に書いてあったなんて

364 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 11:27:45 ]
>>362
最早意味不明だし。インライン展開されない限り、参照やポインタ渡しが値渡しになることは有り得ません。
# インライン展開されたらされたで、Func()自体が(その呼び出しについては)消えてなくなるだろうけど。

365 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 11:41:48 ]
>>364
不動小数点数の演算って、足して引いて 0 とか、かけて割って 1 とか、畳んでいいんだっけ?

366 名前:デフォルトの名無しさん mailto:sage [2008/02/12(火) 11:44:28 ]
>>365
実際に最適化されるときに、引き数が明らかなら可能。
そういう意味では、>364は不正解。

367 名前:364 mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 07:30:06 ]
C/C++でGUIを実装する場合、どういった手段が適当でしょうか?(Windows環境)

色々調べてみたところ
・実際の職業プログラマさんなんかはC#やVB.NETみたいなのを使う
・WinAPIを直接、みたいなことは趣味でやる人が使う
(山を登るのに、ロープウェイを使うのが賢いが趣味で山登りを楽しむ人がいるみたいな意味で)

で、実際人に聞くと今度はMFCという意見が出てきました
調べるとWinAPIを糖衣したようなもののように感じたものの情報がすごく少ない

と、こんな感じでして、どっちに進むべきか悩んでいます
やりたいのはどっちだ、というのは手段と目的がryってやつでGUIの実装の手段をどうしたものか、という質問です
C#/VB.NETというものも一応考慮のうちに入れておきたいです
(GUIの実装はC/C++の枠を超えればそれがベターだから、という意見も考慮したいからです)
それではよろしくお願いします

369 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 07:56:45 ]
スレタイ読め

370 名前:360 mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 09:45:00 ]
>>370
アセンブリ知らないという見方なら C の規格上の実行モデルで考えることになり、
その場合にはそれら2つは引数が値渡しである点を除いてほぼ等価。

違いを知りたければアセンブリを見るしかないでしょ。



372 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 09:46:13 ]
コンパイルして逆アセンブルしてみればいいんじゃないの?

373 名前:368 mailto:sage [2008/02/14(木) 10:34:16 ]
すんませんごばく

374 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 11:38:12 ]
>>370
参照で書かれた関数は、ポインタで書かれた関数と同じコードを吐くよ。
その例では、後者と同じと言うことになる。
勿論、後者自体がdouble Func(double * d) {double tmp = * d; return (tmp + tmp - tmp) * tmp / tmp;}
と殆んど同じコードを吐くという前堤でね。

375 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/14(木) 14:55:14 ]
>>375
VC++2003で最適化オプションを全て有効にして、その4つの関数を定義して
連続で呼び出してみたら、インライン展開されて計算は1回だけで結果を
4回コピーするだけのコードになった。完全に同一とみなされてるね。

あと、インライン展開されてないコードではSSEを使っているけど、展開された
部分ではSSEは使ってなかったな。

377 名前:360 mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 23:17:22 ]
>>370
参照はポインタで渡されるので、関数を呼び出す場合は後者の関数が生成される。
インライン展開されるばあいは、最適化されてポインタが使われない前者と同等になるよ。
>>376
2005proではインライン展開もSSE2になってた。
>>377
SSE2のオプションは確認した?

379 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 11:18:29 ]
このスレに来て学んだことは「とりあえず素直に書いておけ」

381 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 12:34:23 ]
結局、最適化器を書いてるのは人間だから、
「彼らが想定する人間であること」
が大事になってくるわな。



382 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 18:45:37 ]
double を参照渡しはまずせんわな。

383 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 20:55:13 ]
たしかに直接にdoubleを参照渡しにすることは無いけど、テンプレートを使うときに引数を参照渡しにすることはよくある。
その結果、doubleを参照渡しにしてしまうことも多々ある。インライン展開なら参照渡しもしっかり最適化されるので助かる。コンパイラ屋さんに感謝だな。

384 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 21:59:07 ]
値渡し用の型を取得するためのテンプレート使うといいよ。

385 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 21:59:30 ]
値渡し用の型、じゃねえや。
そういった引数用の型、だ。

386 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 22:01:08 ]
テンプレートだと、問答無用に値渡ししないか?
と思ったが、bindとかfunctionとか参照渡しだったな。

387 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 22:04:48 ]
特定の基本型のみ値渡しにし、
他の型は全部 const 参照にするってやつ。
要するに boost::call_traits<T>::param_type 。

388 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 23:13:07 ]
凄いことができるんだな。テンプレートって奥が深いな


389 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 23:15:22 ]
つかフツウやるやろ

390 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 23:16:53 ]
まあ実装はかなり泥臭いがな。
基本的に const 参照にして、基本型全部で特殊化。
実際にはもうちょっと階層的に作ってあるけど、
基本的にはそんなとこ。

391 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 04:02:10 ]
コンパイラが場合によって速いほうを選べるように inline にする。
必要な箇所があれば intrinsic でもアセンブラでも使う。

393 名前:ヽ・´∀`・,,)っ━━━━━━┓ mailto:sage [2008/02/18(月) 04:26:20 ]
残念だがそれをaddps1個に翻訳できるほど現時点でのコンパイラは賢くない。だからこそのIntrinsicsなわけで。

394 名前:ヽ・´∀`・,,)っ━━━━━━┓ mailto:sage [2008/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 名前:ヽ・´∀`・,,)っ━━━━━━┓ mailto:sage [2008/02/18(月) 06:40:31 ]
Intel C++ or VC++なら
#include <fvec.h>

でF32vec4を使う。
テキトーにラップしてよし。
あと、インライン化しないとあんまり効果ないよ。
実関数化するとコールのオーバーヘッドに食われる


396 名前:ヽ・´∀`・,,)っ━━━━━━┓ mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 08:29:40 ]
ダンゴさんの連投でスレが活気付いたな

398 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 08:38:46 ]
活気づいたっていうのかよこれは

399 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 10:24:21 ]
1人だけで盛り上がっていては活気付いたとはいえない。
実際に活気付くのは397からだから397の話題振りで活気付いたということにしないと。

400 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 12:36:08 ]
>>400
最後の行に括弧が抜けてた。
};




402 名前:ヽ・´∀`・,,)っ¬ mailto:OH MY LITTLE バール♪ sage [2008/02/18(月) 15:42:20 ]
駄目。それでもスカラにしかならない。

addpsに展開されることが目的なら、配列にして
for(int i=0; i<4; i++) vD[i] = vA[i] + vB[i];

全要素に同じ操作をしてますよってヒントにはループが一番効果的。
手動アンロールしちゃうと効果ない。


403 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 15:57:21 ]
それバールだったのか。釣竿だと思ってたぜ。

404 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 16:10:23 ]
内部をバラの変数にしても配列にしても外からはわからない。
これぞクラスで隠蔽する良さだな。

405 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 04:22:14 ]
>>405
>\in-?trin-zik, -?trin(t)-sik\
>ttp://cougar.eb.com/soundc11/i/intrin01.wav
よって、「イントリンジク」。

407 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 11:33:11 ]
>>405
VC++なら
class Vector4
{
public:
 union {
  float d[4];
  struct { float x, y, z, w; };
 };
};
これでAddをforループにしたら、SSE使ってくれたよ。

408 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/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 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 21:58:16 ]
>>409
x86-64はSSE使う方が速いし、FPUの利用は推奨されていない。



412 名前:ヽ・´∀`・,,)っ━━━━━━┓ mailto:sage [2008/02/19(火) 23:01:55 ]
自動ベクトル化は何故かVC++ではやってくれないね。何年もなるのに未だに対応しない。
まあIntrinsicsを使うのがいいでしょう。

どのみち配列にしちゃうと仮に運よくベクトル化できてもメモリアクセスが必ず発生しちゃうので
性能落ちる。F32vec4かもしくは__m128iから派生するのがヨシ。

413 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 01:49:02 ]
>>410
そういう仕様のベクトル演算クラスって少ないよ。C++でも






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<166KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef