C++相談室 part31
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNGただし質問の前にはFAQに一通り目を通してください。
テンプレートライブラリ(STL含む)に関する質問は
専用の別スレにお願いッス。
過去スレ、関連スレ、関連リンクなどは >>2-9 あたり
0153デフォルトの名無しさん
NGNG0155デフォルトの名無しさん
NGNG0156デフォルトの名無しさん
NGNGライブラリ呼び出しだけで書けると思ってるの?ヴァカ?
0157デフォルトの名無しさん
NGNG処理系もライブラリもコードも示さないで比較もくそもないと思う。
そして処理系もライブラリもコードも示せるなら自分で計測すれ。
0158デフォルトの名無しさん
NGNG標準ライブラリやメソッドコールの差はあるにしても。
0159デフォルトの名無しさん
NGNG数値計算はライブラリの質が大きいが、シミュレーションとか、
もっと一般的に言って物理エンジンなんかはどうなのさ?
0160デフォルトの名無しさん
NGNG全く聞かないけど?
実際は、C≒C++>>>>Java ぐらいじゃないか?
CとC++とJavaで同じ処理を試すということは、
クラスライブラリなどを一切使わないってことだよね?
0161デフォルトの名無しさん
NGNGで、良いんじゃないかな?
0162デフォルトの名無しさん
NGNGあるよ。
expression template などを使わず。単純に見易さとか書きやすさだけを求めると
遅くなるよ。もっともC++ではそういう書き方もできるという意味で、C流に書けば
いいだけなんだけどね。
#expression templateも+,-,*などの単純計算ならなんとかなっても逆行列なんかには
#無力だけど。
0163デフォルトの名無しさん
NGNGって、Cで書けってことか?(w
0164デフォルトの名無しさん
NGNG具体例を希望
0165デフォルトの名無しさん
NGNG162 じゃないけどMATRIX operator+(MATRIX const&, MATRIX const&) とか。
何も考えずに書くと、戻り値で値のコピーが発生して遅くなりがち。
0166デフォルトの名無しさん
NGNG君にはきっと C のほうが向いていると思う。
0167デフォルトの名無しさん
NGNG最高実行速度という意味では厳密に C++ == C ってことでは?
それに加えて、C++より広範囲の抽象化をサポートしていわけで。
(仮想関数ならそれなりの実行時コストをはらって、また、templateなら
実行時コスト無しで)
0168デフォルトの名無しさん
NGNGその計算はCだろうが戻り値のコピーは避けられないと思うが?
戻り値最適化を前提にしちゃいかんのはわかるが
Cで書けば同等の役割を持った上で高速に動作するコードを示してほしい
つーか expression template の話してるところで
「何も考えずに書くと」のケースの話されても一体何と何を比べてるんだって感じなんだけど
0169デフォルトの名無しさん
NGNG一番速度差が出やすいと言われるのはこんな場合。C++だと、
Matrix a,b,c,d,e;
for(int i = 0; i < takusan; i++){
a = b*c+d-e;
}
ってな計算。
なーんにも考えず二項計算だけ定義すると、
b*cの結果、それと+dの結果、
-eの結果、それぞれを確保、開放
繰り返してたらそりゃ遅くなるでしょ。
C流に書けば、a.b,c,d,e,tmp,tmp2,tmp3は適当に定義してあって、
関数にはポインタで渡すとして
tmp =(XXX &)malloc(sizeof(datasize) * matrixsize);
tmp2 =(XXX &)malloc(sizeof(datasize) * matrixsize);
tmp3 =(XXX &)malloc(sizeof(datasize) * matrixsize);
for( i = 0; i < takusan; i++ ){
mul(b,c,tmp);
add(tmp,d,tmp2);
sub(tmp2,e,tmp3)
}
で作業域は一回だけ確保しとけばいいってこと。
でも、計算式そのまま書けば計算できるC++流の関数と
C流の関数両方用意しとけばいいからC++が遅いってことにはならないよ。
Cだと見にくい書き方しかできないけど。
あと、式テンプレートは結果の作業域は用意しなくてもいいんだが、
結局計算式そのものをどっかに格納しとかなきゃいけなかったりする。
0170デフォルトの名無しさん
NGNGだった、しばらく書いてなかったもんでスマソ
0171デフォルトの名無しさん
NGNG0172デフォルトの名無しさん
NGNG言いたいことは分かるんだけれども
その例はC++でも
結果を格納するためのオブジェクトと op= の形式の演算子使うだけで
C流の関数なんて使わなくともそこそこ可読性を保ったままパフォーマンスを同等にまで上げられる。
しかもこれ、割とよく知られている最適化テクニックなんであまり適切な例ではないような。
0173デフォルトの名無しさん
NGNGSSE2命令有効にしてコンパイルしてもこれほど速くならないと思う。
C/C++からコールするにしても行/列アクセス順序入れ替えるのは面倒だし、
オーバーヘッドは必ず発生するしね。
0174デフォルトの名無しさん
NGNGIntel系ならそうですね。WSやマックは切り捨てですか?
atlasが速いのは、出来るだけキャッシュに入るように工夫してるのが大きいと思うのですが…。
InterlのMKLなんかはP4のパイプラインの分岐予測を乱さないように最適化されているみたいですし。
そこまで行ったら、言語の問題じゃないような気がする。
0175デフォルトの名無しさん
NGNGファイル名を格納するchar配列があります。
この配列は幾つファイルが有るかわからないので動的に増やせるようにしたいです。
そこで今は以下のようにしています。
int n = 10;
struct FILENAME{ char lpsz[MAX_PATH]; };
FILENAME* files = new FILENAME[n];
が、これってわざわざ構造体なんか定義しなくても出来るようにならないでしょうか。
無理とは解ってますが以下とかじゃ駄目ですし。
char* files[MAX_PATH];
files = new char*[n];
0176デフォルトの名無しさん
NGNG分野ではC/C++より早いって話しだよね?
逆にfortranってC/C++みたいな自由度はないのでは?
ただ、CとC++の高速度ソフトウエアの記述能力といった意味では全く
同一だと思う。
0177デフォルトの名無しさん
NGNGstd::stringとかstd::vector<char>とか使え。C++なんだし。
0178デフォルトの名無しさん
NGNGchar** filenames = (char**)malloc(sizeof(char*)*n);
じゃだめなのかね。
0179デフォルトの名無しさん
NGNGつ[std::vector<std::string>]
0180178
NGNG0181デフォルトの名無しさん
NGNG型名をどう記述してよいかわからないだけなら typedef で十分だし。
実際は「動的配列どうやって作れるの?」ってだけの話なのか?
0182デフォルトの名無しさん
NGNGfiles = new char[n][MAX_PATH];
0183デフォルトの名無しさん
NGNG>C流の関数なんて使わなくともそこそこ可読性を保ったままパフォーマンスを同等にまで上げられる。
>しかもこれ、割とよく知られている最適化テクニックなんであまり適切な例ではないような。
そりゃ、技を駆使すればC++も速くなるよ。
でも、多大なる努力を駆使して得られる処理速度は、誰でもすぐに書けるCの処理速度に
どれだけ漸近させられるかってだけ。
その努力が数値計算ユーザにどれだけ支持されるかってこと。
0184デフォルトの名無しさん
NGNGうーん、ダウト
0185デフォルトの名無しさん
NGNG何言ってんのかわかんない。
void add(MATRIX&, const MATRIX&, const MATRIX&);
みたいなC式のスタイルはC++でもできる。
C++式のスタイルは使いかたによってはパフォーマンスが悪い、それだけだろ。
0186デフォルトの名無しさん
NGNG>Intel系ならそうですね。WSやマックは切り捨てですか?
Pen4 に atlas 使って遅い用途ならWSも糞マックも役にたたんだろうからどうぞ捨ててくれ。
0187デフォルトの名無しさん
NGNGop= と op じゃ実装も記述の手間もろくすっぽ変わらん。
問題なのは可読性が下がることだけ。
>>169が言ってるのは、
a = sub(add(mul(b,c), d), e);
より mul_assign(b,c, tmp); ...(以下略) とする方が早いという以上の何者でもない。
それをC++の演算子オーバーロードに置き換えれば op と op= の違いになる、というだけ。
0188デフォルトの名無しさん
NGNG0189デフォルトの名無しさん
NGNGふーん。Matrix計算の場合+=.-=は確かに使えるね。
*=が使えると思ってる時点でオバカさんだな。
どうやったら使えるか解説してくれないか?
0190189
NGNGA *= 3.0;
とか
A /= 5.0;
とかね。
0192デフォルトの名無しさん
NGNG話のポイントのつかめんやつだな。
CとC++でどこが違うかって言ってるんだ。
>>166でも一時オブジェクトは確保してるだろ。
どこで一時オブジェクトがいらないなんて話になったんだ?
#さらに言うと *= の場合、
中途で確保する一時領域は行単位で済むから * よりも
オーバーヘッドは小さくできるぞ。
0193デフォルトの名無しさん
NGNGCでは作業域使わずダイレクトにできるのか?
出来ないよな。なら特に今回の話に関係無いよな。
で?
0194デフォルトの名無しさん
NGNG作業領域を中で確保して値渡しで返す(もしくはswapする)のと、
外から作業用兼結果用の領域をもらうのとは結構違うと思うよ。
0195デフォルトの名無しさん
NGNGおつむの悪い僕ちゃんだな。
いいかい。
op= を遣う理由で一時作業領域を省略できる以外になにかあるのかい?
Matrixの*=の場合はそうならないから指摘してるんだよ。
##さらに言うと *= の場合、
# 中途で確保する一時領域は行単位で済むから * よりも
# オーバーヘッドは小さくできるぞ。
ハイハイ。がんばれよ。頭だけじゃなく往生際も悪いようだ。
0196デフォルトの名無しさん
NGNGCで書くとこういう関数になると思うが
この時、retとaのポインタが指す領域が別々とは限らないため、
Matrix &operator *=(const Matrix &a);
と関数内部は同一になると思うが、そういうことを言ってるのではないの?
0197デフォルトの名無しさん
NGNGいいでしょう。
*= については、a *= b ではさらに新たな一時オブジェクトを作る tmp2 = a * b; に対して改善が見込めないという部分は認めよう。
でも、Cでこの書き方より速くできるかという部分については納得する意見をもらってないよね。
0198デフォルトの名無しさん
NGNGだーかーらー ret,a,bが全部違った時は作業領域いらないでしょ。
その恩恵はC++のoperatorじゃあずかれないでしょ。
>>197
さっきからでてる三項の関数使えばいいじゃん。
C++だからってoperatorにこだわることないんだよ。
実際に数値計算のライブラリも三項引数の関数用意してるよ。
0200198
NGNGっていうかこの問題、式テンプレート使うとなるとまた変わってくるのかも。
0201デフォルトの名無しさん
NGNG0202デフォルトの名無しさん
NGNG確かにC++使ってるとoperatorとかtemplate使いたくなるよね。
そんな事やってる間にチューンを忘れるとか疎かになりがち。
そう言いつつET使ってキャッシュも意識して頑張るんだけど。
>>199
restrictって言おうとしたけどCだな。それに保証も出来んか。
0203196
NGNGパフォーマンスがどうたら言うてる割に現在のCPUでペナルティ大きいifチェックかぁ。
まぁ想定してるmatrixが俺と違うのかもね。
内部で動的にメモリ確保したりするようなヤツならifチェックくらい別にかまわないか。
0204デフォルトの名無しさん
NGNG結局、出力パラメータに対して
operator の戻り値コピーの部分(最適化してくれないとして)がネックになるって話なのね。
>>200
expression template はないって前提でしょ。
一応、それならパフォーマンスをある程度保ったまま
はるかに直感的に式書けるんだからまあ文句は出ないと思う。
もちろん式格納領域はいるけど今問題の一時オブジェクトのオーバーヘッドはなくなるわけだし
0205デフォルトの名無しさん
NGNGblitzもublasも逆行列なんかを使うのが悪いと言うようなスタンスだし。
実際、逆行列に使ったところで逆に覚えとかなきゃいけない要素が多くなると思う。
0207196
NGNGお前にバカっていわれたくないなぁ。
つか、お前のレスは人格攻撃、見下しばかりでつまらん。
そんなヤツとは議論しても実りがない。お前パスな。
どうぞ、勝利宣言でもなんでもしてくださいな。
>>204
式テンプレート一時期凝った時があるが
4x4のMatrix値返しした時のほうが早くなって愕然とした記憶がある。
あまりに凝ると最適化が効かなくなるんかいな??もしくは単にミスってたかな。
0208デフォルトの名無しさん
NGNGそこはそれでかまわないと思うんだけど、、、
まあ俺が実際に使うのは乗算と加算ばっかりだから要望ないだけかも。
数値計算屋さん(なの?)としてはどういう風にしてほしいものなのかな
0209デフォルトの名無しさん
NGNGちょっとまってチェックするっていっても関数の頭でポインタのチェックするだけだろ?
ループ内部で条件判断するわけじゃないの無視できるでしょ?
ふつう行列演算C++でかくなら演算できるかどうかの行、列数のチェックはするだろうし。
一般にoperator=でもソースとデスティネーションの同一性のチェックはふつーするでしょ?
#行き着く先のET使っても、保守性が向上するとは言いがたいと思うのだが。
#blitz 見やすいか?使いやすいか?
0210198
NGNGあ、ごめん。ちなみに俺は194=198=200=206で189とは違うから。
勝利宣言はしますけど。
まともな行列ライブラリなら行列の乗算は式テンプレート使うんだろうね。
LiDIAってライブラリには3引数の関数あったけど。
0211デフォルトの名無しさん
NGNGその代替として人を馬鹿にするんだってのがよくわかるね。
0214デフォルトの名無しさん
NGNG> operator の戻り値コピーの部分(最適化してくれないとして)がネックになるって話なのね。
最適化なんてしようがないと思う。
0215207
NGNG刺した上で9Fから突き落としたくなったよ。
0216デフォルトの名無しさん
NGNG通報しますた。
0217デフォルトの名無しさん
NGNG3引数の関数とは例えば
A * B * C
を計算するような関数かな?
でもこれを計算する場合でもtmp領域は必要だよ。
数学上、2項演算しか定義されてないから(それで十分だから)
2項の計算結果をどっかに保存しないと次項の演算に移れない。
ただし、3項以上の演算を定義することでtmp領域の確保回数を
減ずることはできる。
実際、newmatなんかは行列計算の開始宣言、終了宣言して2項毎の
tmp確保を避けてたと思う(随分前に使ってたので記憶が定かでない)。
0219デフォルトの名無しさん
NGNG>>177や>>179は無視か?
0220デフォルトの名無しさん
NGNGキャッシュラインのサイズに応じたベクトル計算の自動分割とかしてくれるのかな・・・
0221デフォルトの名無しさん
NGNG0222デフォルトの名無しさん
NGNGこんな感じ?
struct Matrix matrix_mul(struct Matrix a, struct Matrix b) { ... }
0223デフォルトの名無しさん
NGNG0224デフォルトの名無しさん
NGNGttp://seclan.dll.jp/c99d/c99d07.htm#dt19990802
一応Cでもinline使えないわけじゃないが。
0225デフォルトの名無しさん
NGNGinline にすれば100%早くなるってもんでもない。
無駄にプログラムサイズが大きくなると、キャッシュミスが多くなるし。
inline があれば、高速化のために手動で関数を展開しちゃうという
愚行に走らなくて済むのは確かだけど。
あと、C言語でもコンパイラによっては inline 展開するようになってるし。
0226デフォルトの名無しさん
NGNGポインタ使え。
0227デフォルトの名無しさん
NGNGcout << "終了しますか? Yes = y, No = n" << endl;
}while(cin.get() != 'y');
このコードを実行して、「n」を入力すると
「終了しますか? Yes = y, No = n」の部分が二回表示されてしまいます。。
キチンと表示させるには、どうしたら良いのでしょうか?
0228デフォルトの名無しさん
NGNG????
0229デフォルトの名無しさん
NGNGdo{
}while(cin.get() != 'y');
0230デフォルトの名無しさん
NGNGcout << "終了しますか? Yes = y, No = n" << endl;
} while (cin.get() != 'y' && cin.get() != '\n');
0231230
NGNG0232230
NGNGdo {
cout << "終了しますか? Yes = y, No = n " << endl;
} while (cin.get() != 'y' && cin.get() == '\n');
0234デフォルトの名無しさん
NGNG>222は皮肉じゃないの?
0235デフォルャgの名無しさん
NGNGstruct Matrix {
struct Matrix_t *m;
};
0236デフォルトの名無しさん
NGNG>>169
>結局計算式そのものをどっかに格納しとかなきゃいけなかったりする。
そのような式オブジェクトは理想的な最適化の結果
コードから排除されるだろうというのがET支持者の一応の主張ではあるんですが・・・.
>>172
三項以上の演算,例えば行列におけるa + b + cなどにおいては
op=の形式では抽象化によるペナルティを喰らう可能性は残ると思います.
0237デフォルトの名無しさん
NGNG以下のようなコード(中途半端な擬似コードで申し訳ない)だと192さんの指摘するように,
一時オブジェクトは1行分だけで済むように思えるのですが違うのでしょうか?
Matrix &Matrix::operator*=(Matrix const &rhs)
{
assert(*thisの列数==rhsの行数 && rhsの行数==rhsの列数);
Row tmp;
for(size_t i = 0; i < *thisの行数; ++i){
tmp = *thisのi行;
for(size_t j = 0; j < *thisの列数; ++j){
*this(i, j) = 0;
for(size_t k = 0; k < *thisの列数; ++k){
*this(i, j) += tmp(k) * rhs(k, j);
}
}
}
return *this;
}
0238デフォルトの名無しさん
NGNG式テンプレートでは左辺と右辺の依存関係の問題は
代入メソッドの選択に一任される形になるかと思います.
通常の代入operator=では一時オブジェクトに結果を保存してから代入(swap)する形を取り,
ユーザが代入による依存関係の問題が発生しないことを保証できる場合のために
式オブジェクトから直接代入するための関数を別途用意する,とか.
>>205
通常,線形代数の数値計算では逆行列を陽に求めるのは最終手段(通常はご法度)なので
blitzやublasのスタンスは適切だと思います.
0240デフォルトの名無しさん
NGNG「俺は俺のやり方がなぜうまくいかなかったかが知りてーんだ。
そんな安易な解決策はとっくに思いついてんだよゴミクズどもが!」
ってちゃんと言わないと駄目だよ。
0241デフォルトの名無しさん
NGNGrhsが正方行列じゃなかったら困らない?
あと、rhsってなんの略?
0242デフォルトの名無しさん
NGNGなんで正方行列である必要があると思うの?
rhs = right hand side
0243デフォルトの名無しさん
NGNG列数が変っちゃうから。
なるほど。right(left) hand valueしか知らなかった。
0244デフォルトの名無しさん
NGNG0246デフォルトの名無しさん
NGNGほんとだ。よく見てなかった。でもそうじゃない場合は困るよね。
Matrixの乗算っていうのはたまたま出た例で、op=で一時オブジェクトが必要なときは
C式のスタイルよりパフォーマンスが悪くなるっていうのがもともとの議論。
0247デフォルトの名無しさん
NGNGcopy on write とか使うようにするのはどうかな・・・
オーバーヘッドもたいしたことないと思うんだけど。
0248デフォルトの名無しさん
NGNG>blitzやublasのスタンスは適切だと思います.
逆行列のETなんかはやろうとしてもできない。もしくはパフォーマンスの向上、
リソースの節約に寄与しないからこそ提供できない。
できないってのとやらないのは違う。
技術的にET実装は非常に難しいことをはっきり言うべき。難しいので提供できませんでしたと。
それを数値演算で逆行列を使うのはおかしいなどというのはイソップの狐と同じ。
0249デフォルトの名無しさん
NGNG作業領域はほとんどいらないし、逆行列のひとつの成分を計算するのに
もとの行列のすべての成分が関係するから式テンプレートを使うメリット
はまったくないな。
式テンプレートを使わず逆行列のメソッドを提供すればいいのになんで
blitz++はやらないのかね?
それを使うかどうかはユーザが決めればいいんだがな。
0250デフォルトの名無しさん
NGNG0251デフォルトの名無しさん
NGNGC++ が苦手というか、operator overload で「数式っぽい見た目」でプログラミング
するのと相性悪いんだと思うよ。
これが 4x4 行列と 4 次ベクトル限定で、ベクトル演算用のレジスタ積んでる
プロセッサだと話が変わってくるけど。演算子オーバーロードを使う場合でも、
o 演算子に対応する関数をインライン展開
o 行列やベクトルの要素がコンパイラ最適化によってうまくレジスタに乗る
と、陽に関数呼び出しを行う C スタイルの書き方より早くなることもある。
0252デフォルトの名無しさん
NGNGC++でもCのような書き方をするなら別に苦手ではない。
それでも効率より見やすさや安全性を考えてクラス化してるんだと思う。
■ このスレッドは過去ログ倉庫に格納されています