プログラムの高速化について語る
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNG速いプログラムをつくるテクニックを教えて下さい。
0002デフォルトの名無しさん
NGNG迷スレの予感
00031
NGNG0004T=M^-1
NGNG0005デフォルトの名無しさん
NGNG0006デフォルトの名無しさん
NGNGるーぷをけずる
一.いんてるしーこんぱいらで
さいてきかこんぱいるする
0007デフォルトの名無しさん
NGNGそんな小さい行列 高速化するまでもなし
普通にガウスで解けば?
0008デフォルトの名無しさん
NGNG追加ツッコミ
ループアンローリングすれば削らなくてもそこそこ速くなると思われ
0009デフォルトの名無しさん
NGNG00101
NGNG0011デフォルトの名無しさん
NGNG0013デフォルトの名無しさん
NGNGツールに応じて上手に設計しなさい
0014デフォルトの名無しさん
NGNG8割の時間を消費している2割のコードを探す。
0015デフォルトの名無しさん
NGNG0017デフォルトの名無しさん
NGNG0018デフォルトの名無しさん
NGNG・自分で下手にアルゴリズムを発明しない
・予想外に遅いならソースを一度捨てる
0019厨房
NGNGこれってVC++にもあてはまるのか
0022デフォルトの名無しさん
NGNGウィノグラード法を使えば速くなるかとほんのり思う
無理かな
0023デフォルトの名無しさん
NGNGどこが実際に遅いのかを計測しろってこと。
計測するツールはプロファイラっていう。
ソース見て遅そうとか思っても実際にそれが足を引っ張ってるとは限らない。
呼ばれる回数その他の条件によるし。
>>14 と重なるが。
で、足を引っ張ってる場所が分かったら
まずはアルゴリズムを見直す。処理量自体を削減するのが吉。
どうあがいても理想的な最小の作業しか処理していない様子になった上で
まだ遅いのなら、またプロファイルしてその時点で一番足を引っ張っている場所を再チェック。
すでに最小限の処理らしい場所が遅い原因となってしまったら、やっと小手先最適化スタート。
場合によってはアセンブラの特殊命令使うとかね。
00241
NGNG鬱だ死のう
00251
NGNGvoid StartTime(void)
{
cout << "計測開始" << endl;
tTemp1 = clock();
}
double StopTime(void)
{
double tTemp2 = (double)(clock() - tTemp1)/CLOCKS_PER_SEC;
cout << tTemp2 << " Sec." << endl;
return tTemp2;
}
00261
NGNGclock_t tTemp1;
0027デフォルトの名無しさん
NGNG#Stdでつかえたっけかな?
0028デフォルトの名無しさん
NGNG最適化が良くなってるとか
0029デフォルトの名無しさん
NGNG逆にコンパイラの最適化を阻害することがあるね。素直に書いたほうが速いと。
また、ライブラリ関数があるのに手で同じ処理を書くと却って遅いってのもよくあった。
昔はどんなパターンでどんなコードが出るのか、いちいちアセンブリ出力してチェックしたなあ。
最近はそこまでこだわる必要がほとんどなくなってしまったが。
この特徴は覚えてもコンパイラのバージョンが変わっただけで事情が変わるしな。
そういえば最適化キチにはWatcom C++は面白かったな。今はオープンソース化の準備中だっけ?
関数の属性にどのレジスタを壊さないとかの情報をつけられて、コンパイラがそれを元に最適化してくれたりした。
特にインラインアセンブリで関数書くのに有利だった。
ライブラリ関数もかなり最適化がすごかった覚えがあるな。
今のVCのほうが最適化は進歩してるかもしれんが。
0030デフォルトの名無しさん
NGNG0031デフォルトの名無しさん
NGNG誰か情報きぼんぬ
0032デフォルトの名無しさん
NGNGジャンプしないように気をつけれ
0033デフォルトの名無しさん
NGNGでもパソコン用だと そんなことしてもCPUが違えば意味ないから
DSPなんかだと
レイテンシが命令によって違うとか、読み書き先で違うとか
の条件でかつ組み合わせの条件がとかなると
自分でツールでも作らんとなあ
0034デフォルトの名無しさん
NGNG同等以上に効くのは利用状況や用途を考慮して内部アーキテクチャを変更すること。
初期の設計と実際の利用状況にギャップがある場合じゃないと成り立たんけどね。
そういう場合には数倍の改善が見られることもある。ま、普通できんが。
0035デフォルトの名無しさん
NGNG0036デフォルトの名無しさん
NGNGまさに最適化ですな。
最適コード ←→ 汎用コード
動作の前提条件を絞ることで性能を向上するが
反面、汎用性は落とすのが最適化なんだしな。
最適化は常に大局(全体の構造、設計)から攻めるのが効果絶大なんですな。
0037デフォルトの名無しさん
NGNG楽なプログラムを早く作って、速いコンピュータの前でコーヒーを飲んで眺めるか・・・
それが問題だ。
0038デフォルトの名無しさん
NGNG関数呼び出し時のオーバーヘッドは特にループ処理で困らされる。
不必要に実数演算を行わない。
整数演算に比べて速度に劣る。
不必要にint型やlong型の変数で演算を行わない。
char型でも良いときは、そちらを使う。その方が速い。
細かな配慮が速いプログラムを生む。
0039デフォルトの名無しさん
NGNG0040デフォルトの名無しさん
NGNG○構造化を先に心がけるべし
×関数呼び出し時のオーバーヘッドは特にループ処理で困らされる。
正しく構造化したなら困る程のオーバヘッドではない筈
○不必要に実数演算を行わない。
×整数演算に比べて速度に劣る。
とは限らない。expとか内臓関数を整数で書くより速い場合もあるからね
○不必要にint型やlong型の変数で演算を行わない。
×char型でも良いときは、そちらを使う。その方が速い。
とは限らない 特に一昔前のチップではcharが混在するとストールする場合あり
0041デフォルトの名無しさん
NGNGそうそう。(実数の話)
途中で実数計算が必要な場合、整数にしたり実数にしたりなんて変換かけると
そのほうがコストがかかることもある。徹頭徹尾実数にしたほうが速かったりね。
それと、乗除算命令の処理時間も実数のほうが速いプロセッサもあるよな。
0042デフォルトの名無しさん
NGNGint型のほうが速いんでないの?
0043デフォルトの名無しさん
NGNGかと言ってキャッシュ効率を考えてintを避けてucharにしてもいいの?
つまりはmov vs movzxの実行スピードの話なんだけど。
0044デフォルトの名無しさん
NGNG実数乗算が十分早くなったからできるようになったのだけど、
実数演算の順序を妨害したり結構面倒。
0045デフォルトの名無しさん
NGNG0046デフォルトの名無しさん
NGNG004743
NGNGhttp://www.intel.com/design/pentiumiii/sml/245043.htm
0048デフォルトの名無しさん
NGNG平均的なC/C++コードを高速に動かすことを目標にしているハズ。
映像処理・音声処理などのケースを除けば、
とにかく素直なコーディングをするのが長期的にはベストの戦略と存じます。
0049デフォルトの名無しさん
NGNGhttp://pc.2ch.net/test/read.cgi/tech/1006834463/926-932
005043
NGNGBOOL a;
bool b;
for(...) a = TRUE; // mov dword ptr [addr_a], 1
for(...) b = true; // mov byte ptr [addr_b], 1
代入は確かに語長が関係するね。(mem to memのopだし)
問題は
for(...) if(a) c = 1; // 速い
for(...) if(b) c = 1; // 遅い
これはやっぱパーシャルレジスタストールだね。
特に何の解決にもならんけど、そうか。boolって1byteだったのね。。知らんかった。。
0051デフォルトの名無しさん
NGNGpen4だとSSE2で逆になる?
0052デフォルトの名無しさん
NGNG0053デフォルトの名無しさん
NGNGexecve(2)のベンチマーク
0054デフォルトの名無しさん
NGNGメモリ帯域の問題があるから、float < doubleにはならないとおもう。
0055769
NGNG>>54
メモリの帯域もあるけど、
そもそも同時演算数が半分になるから半分以下の速度になる。
SSEでfloat4個同時演算できるのが、
SSE2でdouble2個だから。
レイテンシ変わってるはずだが、2倍も変わってないだろう。
つーことでSSE2はfloatで精度が足りない場合くらいにしか使えない。
0056デフォルトの名無しさん
NGNGPen3のSSEは、float4個に2クロックかかる、って
肉系が書いてたような。
0058デフォルトの名無しさん
NGNG0059デフォルトの名無しさん
NGNG( ・∇・) < カステラ
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 1番!
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 電波は
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
(;´Д`) < 2ch!
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 3時の駄スレは
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ゚Д゚) < 晒しage!
| っ |っ \________
⊂ノ〜
∪
0060デフォルトの名無しさん
NGNG0061デフォルトの名無しさん
NGNG( ・∇・) < カステラ
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 1番!
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 電波は
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
(;´Д`) < 2ch!
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∇・) < 3時の駄スレは
| っ |っ \________
⊂ノ〜
∪
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ゚Д゚) < 晒しage!
| っ |っ \________
⊂ノ〜
∪
0062デフォルトの名無しさん
NGNG0063デフォルトの名無しさん
NGNG0064デフォルトの名無しさん
NGNG0065元祖 Matrix4x4^-1
NGNGありがとう。
お礼に、いいこと教えてあげよう。 float型をint型に変換する、VC++の内部関数__ftoi()めちゃ遅い。
例えば、こんなシチュエーションあるでしょう
float dot = dotproduct3( &v1, &v2 )
int r, g, b;
r = (int)(material.r * dot * 255.0f);
g = (int)(material.g * dot * 255.0f);
b = (int)(material.b * dot * 255.0f);
V-TUNEでアナライズすると、このキャストがかなりボトルネックになっていることがわかります。
0066デフォルトの名無しさん
NGNG膨大な量のHPから瞬時に探すなんて不可能です。
http://pc.2ch.net/test/read.cgi/tech/1012536901/909
でも聞いたのですが、レスが付かないのでここで聞きます。
0067デフォルトの名無しさん
NGNG1.常にWebページをあちこちから集めまくってキャッシュしてるから。
2.Linuxマシン1万台のクラスタリングの威力。
006866
NGNGHPの内容はハードディスクにでも覚えているのでしょう。
でも、単純にHD内から検索キーを探しているだけでしょうか?
もちろんコンピュータの処理能力を増やせば速くなりますが、、、
一つ思い付いたのは、
検索キーと検索結果をキャッシュに入れておく方法です。
これなら同じ検索キーなら瞬時に出ます。
他にどんなことやっているのかな・・・
0069デフォルトの名無しさん
NGNG0070デフォルトの名無しさん
NGNGAltaVistaは、Alphaマシンの並列処理で、オンメモリ検索だったはず。
007166
NGNG検索キーをキャッシュの中から探すのではなくて、
あらかじめ、検索キーとその検索キーでヒットするHPを対応付けておくんだ。
キーのハッシュ値を使えばそのまま配列が使えるし、
検索結果の順番もあらかじめ決めておけるし、
かなり速くなりそう。
全HPをメモリ上に置く必要がないし、、、
0072デフォルトの名無しさん
NGNGなんだネタだったか。
007366
NGNG違うの?
007466
NGNGこれより速い方法はないですよね?
誰か教えて下さい!
0075デフォルトの名無しさん
NGNG算術関数は極力使わないほうがいいね。
テーブル作ってインデックスジャンプしたほうが効率いいし
0076デフォルトの名無しさん
NGNG放置プレイも可哀想だから、一応レス
メモリ確保しなくていいから。
確保する手順もオーバヘッドもなくなるから効率いいでしょ。
まぁいつもいいとは言わんけど・・・
0077デフォルトの名無しさん
NGNG最近のPCでは、ほとんど速度が変わらないのよ。
0078デフォルトの名無しさん
NGNGいったい何に比べて速いのでしょうか。
0079デフォルトの名無しさん
NGNG単語でも、長い文章でも、検索に要する時間は同じだけど。
008066
NGNGハッシュ値を求めればあとは同じ速度です。
>78
配列じゃない?
0081デフォルトの名無しさん
NGNGアルゴリズムは複雑だが改良すれば処理が2時間で終了可能だが、改良に2週間
かかりそうだ。
このプログラムが必要なのは2週間後。
どうする?
このまま行く? 改良に着手する?
0082デフォルトの名無しさん
NGNG二回以上なら後者
0083デフォルトの名無しさん
NGNG0084デフォルトの名無しさん
NGNG0085デフォルトの名無しさん
NGNG>>81は、ひっかけ問題だよ。
2週間後に必要なのは、"プログラム"つまりソースコードであって、
このプログラムから導かれる結果ではない。
改良するかどうかは、
仕事の重要性・顧客の重要性・技術者の良心・日常の忙しさ
などから決める必要がある。
0087デフォルトの名無しさん
NGNGパソコンなら算術計算は精度が荒くてよければ10クロック程度で可能です
一方テーブルをひくのは、1Gのパソコンで100Mのデータバスで やっぱり10クロック
2Gのパソコンなら20クロックで逆転してしまいます
0088デフォルトの名無しさん
NGNG確保する必要ないってどういうことですか?
newやらmallocやらする必要があるのでは?
厨房でスマソ
0089デフォルトの名無しさん
NGNG0090デフォルトの名無しさん
NGNGC標準のmemcpy()、memset()と比べてめちゃめちゃ遅いDEATH……。
組み込み関数相手やからしゃーないねんけどなあ。
いずれ気兼ねせずに使えるよーになってほしー。
009183
NGNGソースが必要なのか、実行可能ファイルが必要なのか、
どちらとも取れますが、そもそもどっちでも構わない。
誰が「プログラムから導かれる結果」を二週間後に必要と言っているのか・・・。
0092デフォルトの名無しさん
NGNG0093元祖 Matrix4x4^-1
NGNG(__ftoi の続き)
じゃあどうするかというと、それは、"Game Programming Gems 2" に、トリックが載っています。
0094デフォルトの名無しさん
NGNG{
__asm fld f
__asm mov edx,int_pointer
__asm FRNDINT
__asm fistp dword ptr [edx];
}
某ソースから引っ張ってきたが、こーいうのか?
ちなみに>>65のは四捨五入したほーがよいと思ー。
0095デフォルトの名無しさん
NGNG1/60秒毎に演算結果を求められるプログラムを1年間かけて作っていますが、なにか?
0096元祖 Matrix4x4^-1
NGNGそれだと何の工夫もない、もろストレート組みだよね。 ラウンディング(frndint) のクロックサイクル数って幾つだろう? それに拠っては遅い。
"Game Programming Gems2" のやつは、マジ、トリッキーだよ。
アセンブラで書くとこんな感じ。 ちなみにBIASの値は、本でみてみて。
fld dword ptr [f]
fadd dword ptr [BIAS]
fstp dword ptr [intValue]
mov eax, [intValue]
sub eax, [BIAS]
0097デフォルトの名無しさん
NGNG今のCPUは命令実行速度よりもメモリアクセス速度の方が何倍も遅いから、
>>87はそのテーブルをひく作業の方が速いとは限らないと言ってると
思うんだけど。もちろん遅いとも限らないが。
0098デフォルトの名無しさん
NGNG0099デフォルトの名無しさん
NGNGむ、ここにもなんかあったぞ。float→int変換。
まだカンペキには理解してないんだが、
浮動小数の仮数をそのまま整数に換えちまうわけか。
んで、下は10万回変換させてみた結果。ループ含む。
0.015306 secs : normal cast
0.003773 secs : Real2Int
0100デフォルトの名無しさん
NGNG0101デフォルトの名無しさん
NGNG平方根やhypotや3角関数は整数で計算してるけどね
0102デフォルトの名無しさん
NGNG0103デフォルトの名無しさん
NGNG0104デフォルトの名無しさん
NGNGあれは8086-8087間のインターフェイスを簡単に取れるようにするために
考えられたアーキテクチャなんだよな。
コプロセッサを内蔵した今となっては、何でいちいちメモリを経由して
データを受け取らなきゃならないのかわからん。
ええ、スタック内ではレジスタ−レジスタ間演算も可能ですよ。でも
C言語の実数演算の式をそのように最適化してくれるコンパイラは見た
ことない。
0105デフォルトの名無しさん
NGNG0106デフォルトの名無しさん
NGNG実装によるけど、floatを多用するような3D系とかだと、hypotも平方根も3角関数も、floatに統一した方が速いと思う。
sqrtも三角関数も、FPUのインストラクションがあるからね。
0107デフォルトの名無しさん
NGNG確かに、昔はどうであれ、FPUのレジスタに値をロードするのに、メモリを経由しなきゃいけないのはタコだと思う。
fstp dword ptr [memory]
mov eax, [memory]
ってやんなきゃいけない。
普通、
fstp eax
ってできそうなものじゃん。
mov dword ptr [ten], 10
fld dword ptr [ten]
って感じで、即値もダイレクトにロードできないしね。
fld dword ptr 10
ってやりたいじゃない。
0108デフォルトの名無しさん
NGNG過去との互換性を保つためだからアーキテクチャまで変えるわけにはいかないだろ。
3D NowとかSSEとか使いこなせない頭で安易に批判するんじゃねーよ
0109デフォルトの名無しさん
NGNGちまちましたしょーも無い命令追加ばっかりすんな!>Intel&AMD
0110デフォルトの名無しさん
NGNGマーケティング戦略だからしょうがない。
クロック数を上げるか、命令を追加するのが
消費者にとって一番分かりやすい指標だから。
0111デフォルトの名無しさん
NGNGこうできたらよかったのにっていう話してるんだろ。
何を根拠に、そんなしょうもないことではりきってるわけ?
SSEは、ディフューズ光計算とかの高速化に使ってますが何か?
0112デフォルトの名無しさん
NGNG( ´ー)ρ┳┻┳°σ(ー` )
0113デフォルトの名無しさん
NGNG「インタプリタを使っているならコンパイラ言語に乗り換える」という意見が出ましたがこれって最適化って言いますか?
また、「速いマシンを購入する」も最適化ですか?
0114デフォルトの名無しさん
NGNG問題の解決手法の1つではあるな。
011588
NGNG0116デフォルトの名無しさん
NGNG何が知りたいのかわからん
0117デフォルトの名無しさん
NGNGおれも解らん。
レス先間違えている?
0118デフォルトの名無しさん
NGNG通常、N個星があれば、1回の計算にN*(N-1)回の演算が必要だったのを
擬似アルゴリズムを使って高速化できた、という話の詳細をキボンヌ
0119デフォルトの名無しさん
NGNGPrograms in perl (邦題 珠玉のプログラミング) かなんかで見かけたような
0120デフォルトの名無しさん
NGNG親切なオレ様がレスしてやろう。
まず、レス番号を間違えてるな。>>58の質問に>>76という回答があって、
それに対して>>88と訊いてるわけだろ? 質問するときは、ミスするな。
回答するときにミスするのは「恥ずかしいやつ」として晒されるだけだが、
質問するときにミスすると、そもそも回答が返ってきにくい。
で、>>76の回答の意味だが。これは、「関数の値渡しとポインタ渡しの違い」
の意味で、「メモリ確保しなくていいから」と答えてあるのだ。
もし58=88=115なら、58は多分そういう意味で訊いたのではないはずだろ?
「なんでポインタって○○より速いんですか」という形で訊き直せ。
(´-`).。oO(と偉そうに回答してみて、>>76の意図が全然違ってたら恥ずかスィ…)
012188
NGNGまさにその通りだYO
0122こまかいけど
NGNGコピーによるオーバーヘッドを嫌うから
>「関数の値渡しとポインタ渡しの違い」
引数への
かな。揚げ足捕りに近いのでsage
0123デフォルトの名無しさん
NGNGVC++が吐くアセンブリコードってプロジェクト設定で簡単に見られるやん〜。
今までいちいちデバッガで確認してた俺ってなんなんですか一体。
Winでの開発始めた頃に、最近のcl.exeには
そういうオプションないんだよ〜んみたいな話をどっかで聞いて
ああ、MSならやるかもなあとか勝手に納得してしまってたよ。
0124120
NGNGいや、適切な指摘だと思うぞ。
>コピーによるオーバーヘッドを嫌うから
そう、それ。俺も「メモリ確保」って言ってしまうのは
しっくり来なかったんだが、適切な言い回しを思い付けなくて、
>>76コピペで済ましてしまった。
>引数への
こっちは素で気づいてなかった。確かに俺の表現だと、
ナナメ読みしてると関数ポインタと誤解しやすい気もするから、
引数って単語は必須だな。
0125デフォルトの名無しさん
NGNGプロジェクト設定ってどこで変えるんですか?
あと、アセンブラの命令毎に実行速度書いてある資料って
どうやって手に入れてます?
0126デフォルトの名無しさん
NGNG機械語の実行速度って、それこそ CPU メーカーが出している資料
くらいしかないが。ただ、日本語化されていないことも覚悟してな。
もっとも、今の CPU なんて、見かけ上はほとんどの命令が1クロッ
ク以内に終わるけど。
インテルの IA-32 プロセッサのデベロッパーマニュアルなんて、
3分冊のPDFで合計 25.2MB……日本語化してくれていることに感謝(w
0127デフォルトの名無しさん
NGNG0128デフォルトの名無しさん
NGNGプロジェクト設定>C/C++のファイルリスティングのカテゴリで
リスティングファイルタイプを「ソースコードを含む」あたりに変更する。
これでオブジェクトファイルと一緒に.ASMファイルを吐いてくれるハズ。
0129デフォルトの名無しさん
NGNG複数のパイプラインで同時に実行されてるし、
分岐予測が外れた場合のキャッシュ操作とか諸々考えると、
コードの実行クロック数えながら最適化することは
人間技では無いと思はれ
0130デフォルトの名無しさん
NGNGVTuneを使って、がりがり最適化してる例を雑誌だか本だかで見たことあるよ。
0131デフォルトの名無しさん
NGNGたしか内部コードはプロセッサ毎に違う
0132デフォルトの名無しさん
NGNGμOPのことかな?
0133デフォルトの名無しさん
NGNG0134デフォルトの名無しさん
NGNGC++で複素数クラスつくってるんだけど
四則演算でオペレータオーバーロードすると
参照で値返せないよね。
かといって
complex &mul(const complex &a, const complex &b, complex &c)
{
c←a*b
return c
}
とすると可解読性が悪くなってしまう。。。
こんなときどうすればいいっすか?
0135デフォルトの名無しさん
NGNG{
complex c;
c = a * b;
return c;
}
0136135
NGNG0137135
NGNGvoid mul(complex* result, const complex& a, const complex& b)
{
*result = a * b;
}
使う側(例:a*b+c*d)
complex a, b, c, d, e, f, g;
mul(&e, a, b);
mul(&f, c, d);
add(&g, e, f);
まぁまぁの可読性。
0138デフォルトの名無しさん
NGNG{ return a * b; }
comprex result = mul(a, b);
まっとうな処理系ならこれで作成される一時オブジェクトは1個だけ。
オーバーヘッドにはならないよ
0139デフォルトの名無しさん
NGNGNRV (Named Return Value) 最適化ってヤツだね。
0140デフォルトの名無しさん
NGNG>>99
むかーしから似たような事を考えてる人はいるもので、
ttp://webcat.nii.ac.jp/cgi-bin/shsproc?id=BN00584337
とかにも載ってたりします。>その手法
0141デフォルトの名無しさん
NGNGん?それだと134とほぼ同じですよね?
乗算の関数を呼ぶときに
e = a*b + c*d;
のような形で書けてなおかつ
速さが
complex &mul(const complex &a, const complex &b, complex &c)
あるいは
void mul(complex* result, const complex& a, const complex& b)
のような処理ができれば望ましいんですが仕方ないですか.
やっぱり複素演算では言語仕様でサポートしてるFortranに勝てないのでしょうか
悔しい
0142デフォルトの名無しさん
NGNGEffective C++より
> 22項:値渡しよりも、リファレンス渡しを使おう。
> 23項:オブジェクトを返さなければならないときに、
> リファレンスを返そうとがんばるのはやめよう
一時オブジェクトはたぶん最適化で消えるから心配めさるな。
0143デフォルトの名無しさん
NGNGMore Effective C++
項目19:テンポラリオブジェクトの起源を理解する
項目20:戻り値最適化の促進
項目22:単独のopの代わりにop=を使うことを考える
そして最終的な結論。
Exceptional C++
項目20:クラスの機構
引用:
なぜ、標準ライブラリに存在する複素数クラスcomplexを新たに書くのか。
標準ライブラリのクラスにはこれから述べるような多くの問題点がないし、
それらはこの業界で最高の技術を持つ人達の長年の経験に基づいて作成
されたものだ。汝、謙虚な心を持って、再利用すべし。
自分で手作りせず、代わりに既存のコードを、特に標準ライブラリのコードを
再利用すること。標準ライブラリは、速く、簡単で、かつ安全だ。
以上。
0144デフォルトの名無しさん
NGNGいや、やっぱ結構賢いですな、いまどきのコンパイラ君。
class Complex {
double r;
double i;
public:
Complex(double r = 0, double i = 0) : r(r), i(i) {}
friend Complex operator+(const Complex& c1, const Complex& c2);
friend Complex operator*(const Complex& c1, const Complex& c2);
};
inline Complex operator+(const Complex& c1, const Complex& c2)
{ return Complex(c1.r + c2.r, c1.i + c2.i); }
inline Complex operator*(const Complex& c1, const Complex& c2)
{ return Complex((c1.r * c2.r - c1.i * c2.i), (c1.r * c2.i + c1.i * c2.r)); }
; 26 : Complex e = a * b + c * d;
mov eax, DWORD PTR _d$[esp+12]
mov ecx, DWORD PTR _a$[esp+12]
mov edx, DWORD PTR _c$[esp+12]
push esi
fld QWORD PTR [eax]
fld QWORD PTR [ecx]
fld QWORD PTR [edx+8]
fld QWORD PTR [ecx+8]
fxch ST(3)
fmul QWORD PTR [edx]
fxch ST(1)
fmul QWORD PTR [eax+8]
fld QWORD PTR [eax]
fxch ST(1)
fsubp ST(2), ST(0)
fxch ST(2)
mov esi, DWORD PTR _b$[esp+16]
push edi
fmul QWORD PTR [esi]
fld QWORD PTR [edx]
fxch ST(4)
fmul QWORD PTR [esi+8]
fsubp ST(1), ST(0)
fxch ST(2)
fmul QWORD PTR [edx+8]
fld QWORD PTR [esi]
fxch ST(3)
faddp ST(2), ST(0)
fxch ST(3)
fmul QWORD PTR [eax+8]
fld QWORD PTR [ecx]
fxch ST(2)
fstp QWORD PTR _e$[esp+24]
fxch ST(2)
0145デフォルトの名無しさん
NGNG私の意見としては, 本当に速さがほしかったら
>void mul(complex* result, const complex& a, const complex& b)
のように書いたほうがいい, と思っているのですが,
みなさんはどのようにお考えですか ?
ちなみに私はゲームプログラマとかではないので, あまりカリカリに
最適化とかはがんばりたくない, でも数値計算のパフォーマンスは
ある程度求めたいという, ぜいたくな立場なのですが.
どうしても C++ のクラス + 演算子のオーバーロードではパフォーマンスが
でないもので ...
単に書き方が悪いだけかも.
0146145
NGNG主に使っているのは Linux 上の gcc(2.95.3, 3.0.4) とかです.
Intel のコンパイラとかだと, 何も考えなくても
かなり実行速度があがるので, すごいなあと素直に感心しています.
0147デフォルトの名無しさん
NGNG0148デフォルトの名無しさん
NGNGhttp://www.google.co.jp/search?q=Intel%82%CC%83R%83%93%83p%83C%83%89&hl=ja&btnG=Google+%8C%9F%8D%F5&lr=
0149デフォルトの名無しさん
NGNG>>138の書き方でいいんじゃないか?
自然だし
0150デフォルトの名無しさん
NGNG乗算で倍以上速いのですが最適化をかければ同じになりますか?
VC++スタンダードエディションなので最適化かけられないもので
0151デフォルトの名無しさん
NGNG当方VC6Pro.
おれがジャッジしてやるからどこかにアプしてみれ
0152デフォルトの名無しさん
NGNG0153デフォルトの名無しさん
NGNGポインタを使わない
0154デフォルトの名無しさん
NGNGマルチタスクで使えるかとか、いろいろ汎用性を考えると
どうなんだろうか。
0155デフォルトの名無しさん
NGNG0156デフォルトの名無しさん
NGNG0157デフォルトの名無しさん
NGNG>>144にあれこれ付け足して〜
Complex Hoge1(const Complex& a, const Complex& b, const Complex& c, const Complex& d)
{
Complex e = a * b + c * d;
return e;
}
Complex Hoge2(const Complex& a, const Complex& b, const Complex& c, const Complex& d)
{
Complex e;
Complex t1;
Complex t2;
Mul(&t1, a, b);
Mul(&t2, c, d);
Add(&e, t1, t2);
return e;
}
この2つはほぼ同一のアセンブリコードと相成りました。(って当たり前?)
Hoge2式でも、大抵のケースでは無駄になってしまうんじゃないかなあ。
確保済みのComplexに対しての大量一括計算か何かがあれば
有効になってくるかもしんないけど。
0158デフォルトの名無しさん
NGNGinline Complex operator+(const Complex& c1, const Complex& c2)
#if defined(__GNUC__)
return ret(c1.r + c2.r, c1.i + c2.i)
{
}
#else
{
return Complex(c1.r + c2.r, c1.i + c2.i);
}
#endif
0159デフォルトの名無しさん
NGNGってことでOK?
0160150
NGNGいや、自分の書いてるのは単に上に書いてあるようなやつで
難しいことは一切やってません
だから乗算なら
オペレータ * で引数を2つ参照で受けて
return complex(c1.re*c2.re - c1.im*c2.im, c1.re*c2.im + c1.im*c2.re);
だけです。
これとSTLの乗算比較してみてください(最適化なしで)
自作の方が速かったのは気のせいでしょうか?
当然ですが mul(&a, const &b, const &c)を使えば
更に速くなりました
0161150
NGNGコンストラクタも単純に
complex(double _re, double _im) : re(_re), im(_im) {}
としてるだけ。
代入演算子も同じく。
1000万回ループで自作、STLともに
for (int i = 0; i < 10000000; i++) {
a = b*c;
}
を実行して時間測ってます。
0162150
NGNGみなさんの環境では<varray>も速いんですか?
0163デフォルトの名無しさん
NGNGコンパイルしたらすぐ動くコードくらい用意しなよ。
0164145
NGNG行列, ベクトルがまざった数式を, (ほぼ)そのままソースに
書けたらいいなあという思いがあります.
しかもデバッグが容易になると考えています.
確かに昔の人はアセンブラで, mul, add, とか並べていたんだろうけど.
0165デフォルトの名無しさん
NGNG妄想だからそんなコードは存在しないのです
0166デフォルトの名無しさん
NGNG容赦なく演算子オーバーロードが主流とちゃうかな。
まあ、頂点変換とかメッシュ処理とかは
専用ルーチン用意したりハードに任せたりするとして。
0167デフォルトの名無しさん
NGNG> Mul(&t1, a, b);
> Mul(&t2, c, d);
> Add(&e, t1, t2);
関係ないかも知れんが、C++でこの書き方はあんまりじゃないか?
t1.Mul(a, b);
t2.Mul(c, d);
e.Add(t1, t2);
せめてこう書いてくれ。
0168デフォルトの名無しさん
NGNGどっちの書き方もおかしいだろ
0169妄想の150
NGNG{
double re, im;
complex(const double _re = 0, const double _im = 0) : re(_re), im(_im) {} // デフォルトコンストラクタ
complex(const complex &c) : re(c.re), im(c.im) {} // コピーコンストラクタ
complex &operator = (const complex &);
complex &operator *= (const complex &);
};
const complex j(0, 1); // 虚数単位ね
complex &complex::operator = (const complex &c) { re = c.re, im = c.im; return *this; }
complex &complex::operator *= (const complex &c)
{
const double _re = re*c.re - im*c.im;
im = re*c.im + im*c.re, re = _re;
return *this;
}
inline complex operator * (const complex &c1, const complex &c2)
{
return complex(c1.re*c2.re - c1.im*c2.im, c1.re*c2.im + c1.im*c2.re);
}
inline complex &mul(const complex &c1, const complex &c2, complex &c3)
{
assert(&c1 != &c3 && &c2 != &c3);
c3.re = c1.re*c2.re - c1.im*c2.im, c3.im = c1.re*c2.im + c1.im*c2.re;
return c3;
}
0170妄想の150
NGNGちなみにVC++6.0スタンダードでは
500万回の複素数乗算 a = b*c; を実行してかかった時間が
STL:↑の*:↑のmul
8.08:3.51:1.03
でした。やはり最適化すれば差がなくなるでしょうか
0171145
NGNG>void add(Vector* result, const Vector& a, const Vector& b)
方式とほぼ同じような性能が出るみたいなので,
結局はテンプレートによる実装に行き着くようなきがする.
0172妄想君
NGNGSTLのvectorってそんなに速いんですか?
ところで malloc()せずにってどういう意味でしょうか.
厨房の質問でスマソ.確保しないでアクセスしたらエラーが出るのでは?
見にくいので書き直し
>>170 の結果は
STLの a=b*c; が 8.08sec
妄想の a=b*c; が 3.51sec
妄想の mul(b,c,a) が 1.03sec
といった結果になりました。
プロフェッショナルエディション入手するつもりなので
最適化後の結果も調べてみます
0173!=172
NGNG> 妄想の a=b*c; が 3.51sec
> 妄想の mul(b,c,a) が 1.03sec
VC++6.0 で最適化やってみたら
STL : 0.99 sec
妄想 : 0.44 sec
妄想mul : 0.11 sec
だった。
mul が速いのはいいが、STL は何故遅い?
(VC++ のcomplexの operator* はアセンブラのようだが。
<xcomplex> の412行目)
0174関係ない人
NGNG0175145
NGNGいや, STL の vector ではなくて, a = b * c が mul(b, c, a) 方式くらいの
性能がだせるかもしれないという話です. テンプレートなんたらってのは,
Blitz++ でやっているように, テンプレート使って事前にループとかを
展開するって話です.
0176デフォルトの名無しさん
NGNG速くなったと思ったら最適化で丸ごと消えてることもあるし。
0177デフォルトの名無しさん
NGNG> for (int i = 0; i < 10000000; i++) {
> a = b*c;
> }
これ、VC++だと
a = b * c;
i = 10000000;
に展開されてしまうみたいだぞよ。
i を関数外に追い出してみても無駄だった。
なんかこういうののベンチマーク方法論とかないじゃろうか?
実際のコードで使ってみるしかないのか?
0178デフォルトの名無しさん
NGNGVC++(マルチスレッドライブラリ使用)
VC6.0 STL complex<double> a = b * c 2874ms
STLPort complex<double> a = b * c 1021ms
妄想君 a = b * c 1031ms
妄想君 mul(b, c, a) 580ms
BCC5.5.1
BCC STL complex<double> a = b * c 1181
妄想君 a = b * c 1101ms
妄想君 mul(b, c, a) 180ms
VC++6.0の標準STLがクソなだけ。
妄想君のmul()はいい性能出てるみたい
BCCのmulの結果が意外。
0179デフォルトの名無しさん
NGNGvolatile int a;
0180デフォルトの名無しさん
NGNGGCC 標準STL complex<double> a = b * c 3805ms
妄想君 a = b * c 1422ms
妄想君 mul(b, c, d) 971ms
0181デフォルトの名無しさん
NGNGFreeBSD 5-current, g++ 2.95.3
10000000 回計算するのにかかる時間の総計です.
STL complex<double> a = b * c 0.466sec
妄想君 a = b * c 0.510sec
妄想君 mul(b, c, a) 0.261sec
0182178
NGNG標準STL complex<double> a = b * c 109ms
STLPort 4.5.3 complex<double> a = b * c 115ms
妄想君 a = b * c 213ms
妄想君 mul(b,c,a) 94ms
最適化まで考慮に入れるとこの結果のようだ
0183妄想君(なんかこの名前に慣れた)
NGNG一応こっちでも最適化してみた
VC++6.0 Professional SP5, Pen�V500
ループ回数忘れた
デバッグ
標準STL a = b * c 9383ms
妄想君 a = b * c 6038ms
妄想君 mul(b,c,a) 5137ms
リリース
標準STL a = b * c 4556ms
妄想君 a = b * c 4666ms
妄想君 mul(b,c,a) 4496ms
デバッグモードのSTLが異常に遅いのが分からんが
最適化すると変わらない様子…おとなしくSTL使うか.
0184デフォルトの名無しさん
NGNG0185妄想君
NGNG>>164
うちでは行列もライブラリ自作して行列演算は
complex c;
matrix<complex> m1(10, 10), m2 = m1, m3 = m1;
m2=m1*c*trace(m1);
とか
m1 = m2*m3;
とかしてる.
でも行列の乗算の際にテンポラリの行列が必要だから
"*" 使うといちいち行列の宣言が必要なので
遅くなってしまう.
結局 mul(m1, m2, m3)になってしまうんだけど
マクロか何か使ってもっと見やすく
書けないんだらうかと思う春の夕暮れ。
0187デフォルトの名無しさん
NGNGhttp://www.boost.org/
この2つは絶対に入れて、存在するクラスは絶対に作らない。
コレで汎用性を保ったままほぼ限界性能を出せるから。
0188デフォルトの名無しさん
NGNG行列計算あたりは、プロセッサ依存の最適化を入れると性能が上がらん?
和や積を求めるところで SSE 使うとかさ。
0189デフォルトの名無しさん
NGNGいや、だから汎用性を保ったまま、ね。
局所最適化が必要なら当然そうしなければならない。
0190デフォルトの名無しさん
NGNG汎用性 = compile anywhere
の意味なら、別に STL の実装内部で SSE 使っても、STL 側の外部インター
フェースに手を入れない限りは問題ないよね。
Intel C++ コンパイラについてくる <valarray> とか、どうなってるんだろ?
0191デフォルトの名無しさん
NGNGoperator * はおそらく一時オブジェクトに対する operator *=で実装されているだろうから、
最適化の具合によっては
m2 = m1 * c * trace(m1)は
Comprex temp(m1);
temp *= c;
temp *= trace(m1);
m2 = temp;
の仮想コードに展開されるはず。
STLの用にそれなりにきちんと設計されたクラスライブラリは
最適化のこともしっかり考えてるよ。
0192デフォルトの名無しさん
NGNGstlport の valarray はやたら遅いぞ.
0193デフォルトの名無しさん
NGNGこの言葉が余計なんだと思う。
なんか喧嘩売ってんのかって感じだね。
ここの STL がパワーあるから参考にすれば良いとか書けばいいんじゃない。
必要がなくなれば、そのときは作らなければいいだけの話ですし・・・
0194デフォルトの名無しさん
NGNGBoost.org は STL とは関係ない、というか STL で標準に入らなかったが
「これは欲しいだろ」と思うようなクラスがいろいろ入ってる。数学関係だと
四元数とか。
(でも shared_ptr と bind イチオシだよな)
0195デフォルトの名無しさん
NGNG> なんか喧嘩売ってんのかって感じだね。
その程度でカチンと来てると、2ちゃんねる読んでるうちに血管切れるぞ。
気にせず流せ。
0196デフォルトの名無しさん
NGNG0197デフォルトの名無しさん
NGNGちょうど Quaternion が必要なとこだったので, 後で見てみます.
で, valarray<double> をベクトルとみなして v3 = v1 + v2
を計算してみると, mul(v3, v1, v2) の倍くらい計算時間がかかるみたい.
この差をどう見るかだが ...
環境は Pentium3 500MHz, FreeBSD 5-current, g++ 2.95.3 -O2 ね.
0198妄想君
NGNG>>191
行列の場合 a *= b の右辺の行列bを参照で渡すと
結局作業用の行列が必要じゃないっすか?
そこをあらかじめ作業用行列を一つ用意しておく必要が
あるのではないかと...
ア、書いてて気付いたけど、参照で渡したaの行を
ベクトルに保存して計算すれば aの列の数を持つベクトル
を定義するだけで済むのか
それでも作業用行列ごと渡した方がはやくないっすか
妄想版matrix.h貼り付けたいけど
ちと長い...
0199デフォルトの名無しさん
NGNGどこかのあぷろだに上げろ
0201妄想君
NGNGとりあえず今いる場所にはソースないんで明日
作業場から持ってくる
作業場から2チャンネルに書き込めないんで
complexのときもソース貼れなカターヨ、おかげで妄想君と呼ばれる悲しさ
0203デフォルトの名無しさん
NGNGvalarrayを使った行列の乗算
これと比べていいのかな?
#include <iostream>
#include <valarray>
using namespace std;
int main()
{
const int m=1000, k=1000, n=1000;
long mk=m*k, kn=k*n, mn=m*n, in,i,j;
valarray<double> a(mk), b(kn), c(mn), v1(k),v2(k);
for(i=0; i<m; i++)
{
in=i*n;
v1=a[slice(i*k,k,1)];
for(j=0; j<n; j++)
{
v2=b[slice(j,k,n)];
v2*=v1;
c[in+j]=v2.sum();
}
}
a.resize(0); // clear aa,bb,cc
b.resize(0);
c.resize(0);
return 0;
}
0204妄想君
NGNGこれと妄想matrix.hの m1 = m2*m3を比べてみようかと。
0205妄想君
NGNGclass matrix
{
private:
int m_row, m_col;
public:
T *m_pMatrix;
explicit matrix(int row = 0, int col = 0) : m_row(row), m_col(col) { NewMatrix(); } // デフォルトコンストラクタ
matrix(const matrix<T> &m) // コピーコンストラクタ
{
m_row = m.GetRow(), m_col = m.GetCol();
NewMatrix();
int n = m_row*m_col;
T *p1 = m_pMatrix, *p2 = m.m_pMatrix;
for (int i = 0; i < n; i++, p1++, p2++) {
*p1 = *p2;
}
}
~matrix() { DelMatrix(); } // デストラクタ
void NewMatrix() { m_pMatrix = new T[m_row*m_col], assert(m_pMatrix != 0); } // 行列の領域確保
void DelMatrix() { delete [] m_pMatrix; } // 行列の領域開放
int GetRow(void) const { return m_row; } // プライベートメンバへのアクセス
int GetCol(void) const { return m_col; }
void SetSize(const int row, const int col) { DelMatrix(), m_row = row, m_col = col, NewMatrix(); }
T &operator () (int row, int col) // 配列演算子
{
assert(row >= 0 && col >= 0 && row < m_row && col < m_col);
return m_pMatrix[row*m_col + col];
}
const T &operator () (int row, int col) const
{
assert(row >= 0 && col >= 0 && row < m_row && col < m_col);
return m_pMatrix[row*m_col + col];
}
matrix<T> &operator = (const matrix<T> &);
};
0206妄想君
NGNGmatrix<T> &matrix<T>::operator = (const matrix<T> &m) // 行列 =行列
{
assert((m_row == m.m_row) && (m_col == m.m_col));
if (&m != this) {
if (m_row == 0 && m_col == 0) SetSize(m.m_row, m.m_col);
int n = m_row*m_col;
T *p1 = m_pMatrix, *p2 = m.m_pMatrix;
for (int i = 0; i < n; i++, p1++, p2++) *p1 = *p2;
}
return *this;
}
template<typename T>
matrix<T> operator * (const matrix<T> &m1, const matrix<T> &m2) // 行列×行列
{
int row1 = m1.GetRow(), col1 = m1.GetCol(), row2 = m2.GetRow(), col2 = m2.GetCol();
int n1 = row2*col2 - 1, n2 = col2*(row2 - 1);
matrix<T> m3(row1, col2);
T tmp, *p1 = m1.m_pMatrix, *p2 = m2.m_pMatrix, *p3 = m3.m_pMatrix, *p4 = p2;
assert(col1 == row2);
for (int i = 0; i < row1; i++, p1 += col1, p2 = p4) {
for (int j = 0; j < col2; j++, p1 -= col1, p2 -= n1, p3++) {
tmp = 0;
for (int k = 0; k < col1; k++, p1++, p2 += col2) {
tmp += *p1 * *p2;
}
*p3 = tmp;
}
}
return m3;
}
0207妄想君
NGNGつかれたので高速化したのは明日…
つーかようやく今帰宅
ふと思ったけど連続書き込みで荒らしみたい
0208デフォルトの名無しさん
NGNGでも今は時間がない。(;;)
0209デフォルトの名無しさん
NGNGhttp://www.tietew.jp/cppll/archive/274
0210145
NGNG汎用的なやつに対しては上のようなものを書いて,
2x2, 3x3, 4x4 は別に用意するっていうのが吉かなあと思います.
この方式だと 2x2 とかに関してはクラス + 演算子のオーバーロードを
用いたやつでも結構いい性能がだせます.
あと new/delete を malloc/free に変えてみると, 速度の点で
おもしろいことがおこるかもしれません. これは行列のサイズ依存かも
知れないけど.
0211妄想君
NGNG4*4くらいまでは別に用意するのは禿道、
2*2でオーバーロードで十分なのは作業用の配列が必要ないのが原因と思われ。
ところで行列乗算で乗算回数を減らすアルゴリズムを適用したんだけど
馬鹿でかい(200*200くらい)複素行列くらいじゃないと効き目がないことに落胆の色隠せず。
書き方下手なんじゃろうか。
結局上に書いたのをちょっと書き換えて作業用配列も参照渡しするのが
実用的な行列に対しては自己最速。
>>203 に書いたのと比較したんだけど
203の書きかたがまずいのか妄想Verの方が速かった。
vararray使った速いソースきぼんぬる。
0212145
NGNG>2*2でオーバーロードで十分なのは作業用の配列が必要ないのが原因と思われ。
ってどういうこと? 行列の各要素は配列に入れてるんだけど, ひょっとして
x, y, z, w とかいう変数に入れたほうが速い ?
2x2, 3x3, 4x4 で速い要因としては
1. ループが手動で全部展開できる.
2. コンストラクタも matrix(double a11, double a12, double a21, double a22)
とかいう変態的な形が使える.
3. malloc/free がいらない.
4. インラインも展開 OK
5. 逆行列も, 行列式も決めうち可能.
というところかと(ほんとに当たり前のことばかり書いてごめんなさい).
いくつかは賢いコンパイラがよきに計らってくれるんでしょうが ...
0213デフォルトの名無しさん
NGNG0214デフォルトの名無しさん
NGNG規格上0クリア必須だっけ?>new
0215デフォルトの名無しさん
NGNGけどmallocもANSI準拠だと明示的に未開放でもexitした時に
OSにメモリを返す機構が必要なんで多少のオーバーヘッドはある
速度稼ぐんであればOSべったりのメモリ関数つかうのが良いと思われ
0216デフォルトの名無しさん
NGNG0217妄想君
NGNG要するに演算後の要素を直接与えられた行列の要素を使って
書き出せるってことだよねん?
でも考えてみりゃ*=使わなければ値返す行列が必要か。
結局高速にしたい場合はコンストラクタ作るオーバーヘッドなくすのに
mulみたいにするんだろうか、あるいはここまで最適化してくれるのかな。
試してないけどしてくれそうだね。
0218デフォルトの名無しさん
NGNG>OSにメモリを返す機構が必要
はつみみです。
0219145
NGNG>要するに演算後の要素を直接与えられた行列の要素を使って
>書き出せるってことだよねん?
ごめんなさい... 日本語が分からない ...
>結局高速にしたい場合はコンストラクタ作るオーバーヘッドなくすのに
>mulみたいにするんだろうか、あるいはここまで最適化してくれるのかな。
>試してないけどしてくれそうだね。
アセンブラのコード見てないへたれだけど, 最適化してくれると思ってる.
最適化してくれないと complex もうまくいかなかっただろうし.
任意の次元の行列はどうしたらいいのか分からないので, 妄想さんに期待.
0220デフォルトの名無しさん
NGNGテンプレートでどうぞ。い
0221デフォルトの名無しさん
NGNG215 にはコテハン「知ったかクン」を贈呈したいと思うが、どうか?
とりあえず Inside the C++ Object Model とエキスパート C プログラミングを
読んで出直して来い。
0222妄想君
NGNG漏れの素人考えでは
要素はmalloc使わずに
double e11, e12, e21, e22;
と書けるし
乗算に限らず逆行列でもmallocで作業用の行列をつくることなく直接
det = 1/(_e11*_e22 - _e12*_e21);
e11 = det*e22;
とかfor文使わずに書けるし、これなら実行速度が速くなるかなぁと。
って>>212に書いてあるまんまじゃん(鬱
一般行列の乗算は
>>206の
matrix<T> operator * (const matrix<T> &m1, const matrix<T> &m2) // 行列×行列
を
matrix<T> &mul(const matrix<T> &m1, const matrix<T> &m2, matrix<T> &m3)
にして
matrix<T> m3(row1, col2);
を消せばいいんじゃないでしょうか。
いろいろやってみたけど、小さい行列は
>>212のように matrix2とかmatrix3とか専用クラス作って
中くらいの行列(n = 5 〜 100)は↑に書いたmulで
大きい行列(n > 100)はブロック化するのでfinal answer。
STLのvalarrayは...速いの組める人教えて下さい、おながいします。
>>203みたいに使うとどうも遅くて。
0225デフォルトの名無しさん
NGNG照れ屋さんな貴方ってステキ
0226145
NGNG>matrix<T> &mul(const matrix<T> &m1, const matrix<T> &m2, matrix<T> &m3)
で, 満足なんですか ? と煽ってみる(w
224 にもあるように一般的な大きさの行列に対してはテンプレートの
再帰的な利用(expression template)になるんですかね ?
ていうか Blitz++ を素直に使え ?
0227煽られている妄想君
NGNG速くなるってことなんだろうか(しったか。)
いや、C++始めたばっかなんでそんな高度なことは考えたこともなかったYO。
時間あれば勉強したいが当分…
ちなみにBlitz++はVC++なので使用不可〜。
0228煽られている妄想君
NGNGもっとテンプレートの勉強にいいページない?
0229デフォルトの名無しさん
NGNGGeneric Programming with C++ Template
http://pc.2ch.net/test/read.cgi/tech/1008593126/l50
のスレでもそのテの話題があるよん。課題は汎用性と効率の両立。
0230!=189
NGNG遅レスですが, Intel コンパイラの valarray って
きわめてふつうな実装に見えます. C++ の入門の本にのっているやつと
あんまり変わらないような ? 違うんかな, 識者のレス求む.
GNU の valarray は遅延評価をやっているみたいです.
全部参照でデータを持っていて, 代入演算子のところでばばっと
演算しているみたい.
>> 227
GNU のやつは add(v3, v1, v2) とかと同じくらいの性能がでるので,
汎用的な行列は遅延評価を組み込んだものにすれば, いいのでは ?
0232デフォルトの名無しさん
NGNG実際に演算結果が必要になった時点で計算するやり方。
配列同士の計算だと、全部が全部必要ってわけでもないでしょ?
0233煽られ妄想
NGNG積を計算する順序でたいぶ計算量が変わりますから
0234デフォルトの名無しさん
NGNGもうすぐ出るCマガに記事が載るんでしょ?
0235デフォルトの名無しさん
NGNG0236数学に弱いプログラマ
NGNGsinは、0<=x<=PI/4のとき 0.99959257 * x - 0.1615350 * x * x * x
ってのは知ってるんだけど、それ以外調べても見つからず。。。
とりあえず、sinとcos、arctanについて知りたいんだけど。
何がやりたいのかと言うと、複素数ベクトルの直行座標<->極座標の変換なんだけど、
特にarctanが重過ぎてお話にならないのです。
誰か高速な手法教えてください。
ちなみに、SIMDで処理したいので、できれば分岐とかないアルゴリズムをキボンヌ。
0237デフォルトの名無しさん
NGNG入力の角度精度によっちゃあ、テーブル持った方がいいんじゃないか?
0238デフォルトの名無しさん
NGNG>ってのは知ってるんだけど
理解せずに使って平気かい。
それの求め方分かっていれば他のも求められるよ。
0239数学に弱いプログラマ
NGNG>>237
うーん、さすがにテーブルだと、実用的なサイズに収まらないので、
たとえ160〜300クロックかかってもfpatan呼んだ方がマシかも。
>>238
テーラー展開くらいなら多少は。
でも、その式はテーラー展開を途中で打ち切った式より精度が良いとか。
ちなみに、IntelのHPみたら、なんかSSEで各種数学関数を
近似計算してくれるとかいうソースコードを見つけたので
それで解決するかも。5倍は速いみたい。
ほぼフルアセンブラだから、そのまま抜き出して使えば、
かなりの速度向上が望めるかも。
0240デフォルトの名無しさん
NGNGまた、テーブルを間引いて補間多項式も併用できる。
区間が短ければ次数の低い補間多項式でも誤差は小さく抑えられる>>239
0241デフォルトの名無しさん
NGNG絶対値の誤差 2%、角度誤差 0.5度程度だったような...で
8087に勝った記憶あり。
0242デフォルトの名無しさん
NGNG>複素数ベクトルの直行座標<->極座標の変換
自体の回数は減らせないの?
0243デフォルトの名無しさん
NGNGどれくらいの精度でやりたいの?
整数なら分岐有りだけど
ttp://www.infoeddy.ne.jp/~tensyo/prog/ALGO.HTM
整数だけでやればSIMD並の速度が出る場合もあるよ
0244デフォルトの名無しさん
NGNG0245デフォルトの名無しさん
NGNGきゅーすーてんかい
0246デフォルトの名無しさん
NGNGMatrix Inverse()
{
Matrix d;
//行列式計算
f32 d0 = +( (_11*_22*_33)+(_12*_23*_31)+(_13*_21*_32)-(_13*_22*_31)-(_23*_32*_11)-(_33*_12*_21));
f32 d1 = -( (_01*_22*_33)+(_02*_23*_31)+(_03*_21*_32)-(_03*_22*_31)-(_23*_32*_01)-(_33*_02*_21));
f32 d2 = +( (_01*_12*_33)+(_02*_13*_31)+(_03*_11*_32)-(_03*_12*_31)-(_13*_32*_01)-(_33*_02*_11));
f32 d3 = -( (_01*_12*_23)+(_02*_13*_21)+(_03*_11*_22)-(_03*_12*_21)-(_13*_22*_01)-(_23*_02*_11));
f32 s = (_00*d0+_10*d1+_20*d2+_30*d3);
if (s == 0){
//逆行列が存在しない
d.Identity();
return d;
}
//余因子行列計算と係数乗算
s = 1.0f / s;
d._00 = d0 * s;
d._01 = d1 * s;
d._02 = d2 * s;
d._03 = d3 * s;
d._10 = -( (_10*_22*_33)+(_12*_23*_30)+(_13*_20*_32)-(_13*_22*_30)-(_23*_32*_10)-(_33*_12*_20)) * s;
d._11 = +( (_00*_22*_33)+(_02*_23*_30)+(_03*_20*_32)-(_03*_22*_30)-(_23*_32*_00)-(_33*_02*_20)) * s;
d._12 = -( (_00*_12*_33)+(_02*_13*_30)+(_03*_10*_32)-(_03*_12*_30)-(_13*_32*_00)-(_33*_02*_10)) * s;
d._13 = +( (_00*_12*_23)+(_02*_13*_20)+(_03*_10*_22)-(_03*_12*_20)-(_13*_22*_00)-(_23*_02*_10)) * s;
d._20 = +( (_10*_21*_33)+(_11*_23*_30)+(_13*_20*_31)-(_13*_21*_30)-(_23*_31*_10)-(_33*_11*_20)) * s;
d._21 = -( (_00*_21*_33)+(_01*_23*_30)+(_03*_20*_31)-(_03*_21*_30)-(_23*_31*_00)-(_33*_01*_20)) * s;
d._22 = +( (_00*_11*_33)+(_01*_13*_30)+(_03*_10*_31)-(_03*_11*_30)-(_13*_31*_00)-(_33*_01*_10)) * s;
d._23 = -( (_00*_11*_23)+(_01*_13*_20)+(_03*_10*_21)-(_03*_11*_20)-(_13*_21*_00)-(_23*_01*_10)) * s;
d._30 = -( (_10*_21*_32)+(_11*_22*_30)+(_12*_20*_31)-(_12*_21*_30)-(_22*_31*_10)-(_32*_11*_20)) * s;
d._31 = +( (_00*_21*_32)+(_01*_22*_30)+(_02*_20*_31)-(_02*_21*_30)-(_22*_31*_00)-(_32*_01*_20)) * s;
d._32 = -( (_00*_11*_32)+(_01*_12*_30)+(_02*_10*_31)-(_02*_11*_30)-(_12*_31*_00)-(_32*_01*_10)) * s;
d._33 = +( (_00*_11*_22)+(_01*_12*_20)+(_02*_10*_21)-(_02*_11*_20)-(_12*_21*_00)-(_22*_01*_10)) * s;
return d;
}
余因子行列と行列式による4×4逆行列の算出アルゴリズムを書いてみました。
がんばればSIMDで最適化できそうではあるのですが、
ガウス法による算出とどちらが良いと思われますか。
0247デフォルトの名無しさん
NGNG0248デフォルトの名無しさん
NGNG0249デフォルトの名無しさん
NGNG何事もなく過ごせるかと思ったのですが(w
本当は例外投げるべきなんでしょうけど。
0250sage
NGNG47 は読みましたか ?
まさにあなたの知りたいことがのっていると思います.
0251デフォルトの名無しさん
NGNG0252デフォルトの名無しさん
NGNGだって、例外投げるようにしたら少し遅くなっちゃうんですもの。
(by 元の行列を返してる不届き者)
0253246
NGNG今読んだ。うーん流石インテル。
知りたい情報がずばり詳細に。
このやり方は、クラマーっていうのか。
クラマールール英語で言うとかっこイイ。
0254煽られ妄想
NGNGVCはダメ?
■ このスレッドは過去ログ倉庫に格納されています