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


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

C++相談室 part129



1 名前:デフォルトの名無しさん(ワッチョイ dfcf-HvS5) mailto:sage [2017/01/09(月) 14:49:27.56 ID:p96WJVyd0.net]
次スレを立てる時は本文の1行目に以下を追加して下さい
!extend:on:vvvvv:1000:512

C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part128
echo.2ch.net/test/read.cgi/tech/1480172629/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.100【環境依存OK】
echo.2ch.net/test/read.cgi/tech/1478440682/

■長いソースを貼るときはここへ。■
 codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
www.bohyoh.com/CandCPP/FAQ/ (日本語)
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured

730 名前:デフォルトの名無しさん (スプッッ Sddf-8YZg) mailto:sage [2017/03/19(日) 00:17:51.96 ID:UQylyHTkd.net]
お前らのおすすめのデザインパターんおしてて

731 名前:デフォルトの名無しさん (ワッチョイ 738b-UnlH) mailto:sage [2017/03/19(日) 00:18:40.25 ID:F98WB86R0.net]
訂正
誤: F::calc()というシンボルのアドレスがコンパイル時に決まるから、直接呼出しのコードにできる
正: F::calc()というシンボルの呼び出しであることがコンパイル時に確定するから、直接呼出しのコードにできる

732 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/19(日) 00:38:21.66 ID:rBaNXWYpr.net]
>>715
とりあえずRAIIは使っとけ
ナマポをnewする奴は殺害されても犯人に情状酌量の余地が残る

733 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/19(日) 00:38:32.17 ID:Sogj9z7eM.net]
>>715
expression template

734 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:10:03.99 ID:7dJ8iAqk0.net]
>>714
日本語で説明しようとしたのはまずかった。C++で書き直すと、以下。
ただしC++文法には詳しくないので、syntaxErrorは適宜脳内修正よろしく。
意味だけ見てくれ。ソースは>>666から流用してる。

class F {
int _a;
public:
F(const int a):_a(a) {}
int calc(const int x, const int k) const { return k * x + _a; }
};

int main()
{
const F f0(1);
const F f1(2);
std::function<...> f0_1 = std::bind(&F::calc, f0, _1, 3); // 第2引数を固定
std::function<...> f0_2 = std::bind(&F::calc, f1, 4, _1); // 第1引数を固定
std::function<...> f1_1 = std::bind(&F::calc, f1, _1, 5); // 第2引数を固定

call_sub(F0, f0_1, f0_2);
call_sub(F1, f1_1, f0_1);
}

void call_sub(F& f, std::function<...> f1, std::function<...> f2){
f->func(1,2); // (L) 直接呼び出し
f1(3); // (M) コンパイラによっては直接呼び出し、一般的には2段階呼び出し
f2(4); // (N) 2段階呼び出し
}

735 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:10:33.50 ID:7dJ8iAqk0.net]
(L)は必ず直接呼び出しになる。アセンブラなら push, push, push, call
(M)はソース上を精査すれば同型呼び出ししかないことが分かるので
技術的には(L)と同程度まで最適化可能ではあるが、一般的には無理だと思う。
2段階呼び出し時は push, push, push, call, mov, jmp
(N)は異なる形の呼び出しが与えられているので、
技術的に(L)と同じコスト(アセンブラ4命令程度)の直接呼び出しは不可能。
無理にcmpとかやるより普通に2段階呼び出しの方がいいと思う。
だからVCもそうしていると見ている。

それで、std::bindについては詳しい奴が以下見れば実装の見当が付くはずだが、
俺はC++用語に詳しくないので分からん。
ja.cppreference.com/w/cpp/utility/functional/bind
俺が実装するなら、ありがちなのをテンプレートで実装するが、
その場合はポインタサイズはsizeof(int)*2になる。
(メンバ関数へのポインタと、bind済みの値をstructで持つ=内部的な匿名クラスにするから)
VCがなぜ4に出来るのかは分からん、というか計測間違いじゃないかと思う。
(バインド済みの値の分を入れてない)

736 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:11:05.58 ID:7dJ8iAqk0.net]
俺が言いたかったのは、上記(L),(M),(N)ということ。
君の主張は、すべてbind時で確定して、上記(M)(N)も(L)と同じコストで呼べるという主張だと読める。
それは無理。
確かにアドレス自体は確定はするが、
引数をbindしているのだからスタックをその形にしてやらないといけない。
上記(N)の呼び出し、アセンブラ4命令ではどうやっても書けないだろ。
cmp使って書くくらいなら2段階呼び出しで6命令(2分岐)の方がマシ。

cmp使って無理に直接呼びにしたら、
そこに来る可能性のある呼び出し型を全部そこに書かなければならなくなる。
そしてx86はプレディケートを持ってないので、cmpで分岐しないといけない。(ARMは持っている)
それって完全に本末転倒だろ。

それで、std::bindと関数オブジェクトをどう組み合わせたら、
(L),(M),(N)について上記通りアセンブラ4命令程度で呼び出せるのかよろしく。

737 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:17:42.85 ID:7dJ8iAqk0.net]
すまん、重要なところを間違えていたので訂正。
>>719
> std::function<...> f0_1 = std::bind(&F::calc, f0, _1, 3); // 第2引数を固定
> std::function<...> f0_2 = std::bind(&F::calc, f1, 4, _1); // 第1引数を固定
> std::function<...> f1_1 = std::bind(&F::calc, f1, _1, 5); // 第2引数を固定
の2つ目、インスタンスは f0 ね。

std::function<...> f0_2 = std::bind(&F::calc, f0, 4, _1); // 第1引数を固定, f0

ただ結局、変な引っかけみたいになっているだけで意味は同じかな?
まあ訂正しとくけど。

738 名前:デフォルトの名無しさん (ワッチョイ bfcc-UNkP) mailto:sage [2017/03/19(日) 01:31:51.96 ID:i6MRGbY60.net]
まだJAVAガイジ張り付いているのか…



739 名前:デフォルトの名無しさん (ワッチョイ 8330-PVeP) mailto:sage [2017/03/19(日) 01:41:06.04 ID:I9SbzQA70.net]
あんだけ無能な醜態をさらしておいて
ボクはレベルが高いけどちょっと知らなかっただけちょっと間違えただけで済んで
まだ自分のいうことに説得力がある聞いてくれる人がいると思ってるところがもうね…

740 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 01:44:23.31 ID:7dJ8iAqk0.net]
bindの説明読む限り、やっぱこれかなり汎用に作っていて遅いと思うぞ。
ただ一般的にはそこが見えるほど使うことはないと思うが。
アセンブラ的には、

f->func(): 4命令程度(分岐1回)
std::bind経由での呼び出し: 10-50命令程度か?(分岐2回以上)
内部オブジェクト作成方式: 6命令程度(分岐2回)

じゃないかな。

741 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 01:49:16.54 ID:jcDR9uoj0.net]
まぁ、別にスレ違いというわけでもないからいてもいいんじゃない?付き合いたい人が付き合えば。
俺はレスしないけど。

742 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 01:59:32.09 ID:jcDR9uoj0.net]
と、言ったものの、我慢しきれないので撤回します。

>>725
https://godbolt.org/g/SFtHQt

こうなる意味を考えて。
もう一つヒントあげるとstd::function<int()>で受けるとどうなるか見てみたらいいよ。

743 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:14:29.60 ID:7dJ8iAqk0.net]
誰かと思えば>>678か。
じゃあついでに言っておくと、以下だね。

callbacks.push_back([&]{a.func();}); // (O) クロージャ作成が無駄
callbacks.push_back(a->func)); // (P) この書き方は現在出来ないが、こっちの方がいい

JavaScriptでは(O)は無駄だとされる。クロージャが余分にメモリを食うから。
クロージャ無しで書けるならその方がいい。コード領域も無駄だし。
これはC++も同じだし、C++の方が厳しいはずだが。
とはいえstd::bindの仕様が重すぎるのでこちらもイマイチだ。
C++ならどっちが重いかは微妙だね。

なおJavaScriptのbindは「前から順に固定される」だけの仕様なので、
固定した引数分のデータ領域しか各bindインスタンスには必要ない。
というかC++のbindが妙にリッチな仕様なのが謎だが。C++っぽくない。

744 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 02:17:00.87 ID:jcDR9uoj0.net]
>>728
C++なら無駄ではない
終了

745 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:19:33.17 ID:7dJ8iAqk0.net]
>>727
俺には計算済みとしか見えないが、何か操作必要?
-O3外せとかか?

> fn(int):
> lea eax, [rdi+rdi]
> ret
> bind():
> mov eax, 4
> ret
> direct():
> mov eax, 4
> ret

746 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:28:44.92 ID:7dJ8iAqk0.net]
>>727
というかな、根本的に間違ってると思うぞ。

一般的に関数ポインタを使う場合、それは外部から与えられるんだよ。
自分の内部で作って使うって事はない。
(ここでは単純なソースで議論するからそうなるだけで、一般的にはそうではない。
つか、それじゃ関数ポインタの意味がないし)

典型的にはcallbackだよ。外部から与えないと全く意味無いだろ。
で、その場合は当然この手の事前計算とかでの最適化は出来ないんだよ。

747 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 02:33:33.53 ID:jcDR9uoj0.net]
>>731
一時一句同じじゃないと理解できない人だったか。

https://godbolt.org/g/o73pz4

これで理解できますか?

748 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 02:51:38.54 ID:7dJ8iAqk0.net]
>>732
あーお前がアホだということはよく分かったわ。

まともに議論する気なら、お互いが見ているものが同一であることを確認しないといけない。
>>727を見たらアホかと思うのは道理だろ。

そして>>732もアホかと思うよ。関数内部で何を作ってもそれは最適化されるよ。
それは一時変数を除去すればいいだけなのだから。
そうではなくて、例えば以下にしないといけない。

int main(){
auto f = std::bind(&something::func,ptr);
bind(f);
}

int bind(std::function<...> f){
return f(); // bind済みのfを呼ぶコストをここで計測する
}

再度言うが、関数ポインタは外部から与えないと意味無いんだよ。



749 名前:
てかお前ら実は全く関数ポインタ使ってないだろ。
だから使い方自体を知らないんだよ。

これで、bind/関数オブジェクト/クロージャで呼び出しコストを比べてみなよ。
当たり前だが上記だとbind呼んで終わりになるけど、
もちろんその先のターゲット(something::func)が呼ばれるまで見るんだよ。
つまりstd::bind内部のコードもね。それが呼び出しコストなんだから。
それで、あらかじめ計算済みとかいうアホなオチはマジで止めてくれ。
一般的にポインタを与えた場合、それが無理なことくらい分かるだろ。
[]
[ここ壊れてます]

750 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) [2017/03/19(日) 03:14:07.27 ID:jcDR9uoj0.net]
>>733
注文の多いやつだなぁ。

https://godbolt.org/g/R1ljMl

関数ポインタを外から渡すようにかえてやったぞ。
自分で言ってることをC++で書く能力ぐらいあるよね?
次から自分で書けよ。


std::bindに余分なコストなんてない。std::functionの方にある。
ヒントあげたのに全く考えようとしなかったのかな?

751 名前:デフォルトの名無しさん (ワッチョイ 537b-v8EU) mailto:sage [2017/03/19(日) 03:24:22.16 ID:jcDR9uoj0.net]
>>733
なぜか一時変数だから最適化できると信じてるみたいだけど、そう思うなら

int std_function(something* ptr,fn_ptr_type fptr){
std::function<int()> f = std::bind(fptr,ptr);
return f();
}

と書いてみればいい。

>そして>>732もアホかと思うよ。関数内部で何を作ってもそれは最適化されるよ。
>それは一時変数を除去すればいいだけなのだから。
がバカな発言だったと理解できると思うから。

752 名前:デフォルトの名無しさん (ワッチョイ 0f59-Rjy3) mailto:sage [2017/03/19(日) 03:38:13.98 ID:xwQyhAst0.net]
ああ、Javaだと〜とか言ってた人か

753 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/19(日) 08:10:18.88 ID:oCYtEhVi0.net]
>>717
調べても出てこない....
コンストラクタとデストラクタでNewとかするやつだっけ??

>>718
数式を渡して分かりやすくするってのはなんとなくわかったんだけど
逆にごちゃごちゃしすぎてる気がするって印象を受けた

754 名前:デフォルトの名無しさん (ワッチョイ ef6c-i8cA) mailto:sage [2017/03/19(日) 08:15:20.51 ID:gWCLtiPs0.net]
>>737
デストラクタでdeleteやで

expression templateは効果がどうなの?って思い始めてる
普通にコンパイラの最適化に任せた場合とそんなに変わるんかな

755 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/19(日) 08:18:02.91 ID:oCYtEhVi0.net]
>>738
すまん
とかにまとめた
scope抜けたときに必ず処理させるってやつよね
確かに必要なやつだな

コード見やすくってやって逆に色々と設定があると逆に見にくくなるんじゃないか?って疑問が残った
今はあとシングルトンパターンぐらいしかわかんないや

756 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 08:46:03.88 ID:7dJ8iAqk0.net]
訂正ね。
>>733
× std::bind内部のコードもね。
○ std::functionのoperater()の内部のコードもね。

処理系の実行コードも、という意味で書いたが、
std::bindはstd::functionを返すので今回についてはoperator()のコードになるのだよな?
まあ間違っていたら適宜訂正してくれ。分かる範囲だと思う。

>>734
> std::bindに余分なコストなんてない。std::functionの方にある。
これが上記について言っているのならその通り。
ただそれは揚げ足取りだと分かるだろ。それがやりたかったのならどうぞ、おめでとう。
それが分からないのなら君にはこの話は無理だね。
というわけでいずれにしてもこの話は終わりでいい。

757 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 08:47:04.27 ID:7dJ8iAqk0.net]
一応中身は確認した。
>>734については呼び出し側は全部同じコードが出るという事ね。ここまではいい。
問題はその先だ。それは君も分かってるんだろ?だったら何故それをしない?

>>735
> なぜか一時変数だから最適化できると信じてるみたいだけど、そう思うなら
これについては相変わらずそちらが間違いだね。
事前計算済みのコードをドヤ顔で出してきたのはそちらだろ。
それはコンパイル時に「事前計算が出来る」ということがコンパイラにも分かったから。
とはいえ、君みたいな奴も沢山いるのも事実だよ。

> と書いてみればいい。
書いてみたらstd::functionのコードが出た。
中身は今の俺にぱっと分かるようなものではないね。
が、まあ、100命令弱増えているからその分遅いと言える。
だから結論は、直接=ファンクタ<<<<bindになるのかな?
ファンクタは正直ピンとこない。
あとは>>729で無駄がないとドヤ顔のラムダがどこまで速いかだね。
まあ頑張って。

いずれにしても、この話は終わりでいい。
俺が確認したい範囲はもう分かった。

758 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 08:51:40.65 ID:jcDR9uoj0.net]
>std::bindはstd::functionを返すので今回についてはoperator()のコードになるのだよな?

ここまで書いても理解出来ないのかよ…



759 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 09:00:02.50 ID:jcDR9uoj0.net]
>>741
俺はただ知識がないやつをバカとは思わないが、お前みたいな自分が理解出来ないのを相手のせいにしてアホなんて言う奴は本当にバカだと思うよ。

書いておかないと理解しなさそう(=出来なさそう)だから一応書いておいてあげるよ。

std::bindの返りの型はstd::functionでは”ない”

760 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/19(日) 09:08:50.00 ID:EshC/yEQr.net]
>ID:7dJ8iAqk0
コストは 直接=ラムダ=bind <<< std::function
bindとstd::functionは関係無い
functionにbindを重ねればfunctionのコストがそのまま残る

761 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:17:50.63 ID:7dJ8iAqk0.net]
>>743
だから俺はそこら辺までは詳しくないのさ。
繰り返しているとおり、std::bindの説明を読んでも全てを今すぐ理解する知識はないんだよ。
俺はC+JavaScriptだからね。C++はbetterCとして使ってきてるが、
VC++(=CLI)だからSTLを使ったことはなく、.NETだし。

C++特有のテンプレートとか型消去については
「動的型なら何も考える必要ないのに」で飛ばしてきたし、
RAII+スマポについても「そこまで言うならGC言語使えよ」としか思ってない。

だから今、型消去とかも読んでるけど、これを理解するには時間がかかるし、
上記の通りSTLについてもほぼ知らないから、これまたインストールに時間がかかるんだよ。


> std::bindの返りの型はstd::functionでは”ない”
まあそれはさておき、std::bindは何が返るんだこれは?
型消去で無理矢理格納出来るだけなのか?
ただ、実行時はstd::functionのoperator()が呼ばれると思うが、これも違うのか?

762 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 09:26:27.21 ID:jcDR9uoj0.net]
>>745
知らないなら想像で実行時コストとか決めつけるなよ

auto f=std::bind(func);
f();

std::function<int()> f=std::bind(func);
f();

で出力されるコードが違うんだから違うと

763 名前:解るもんだとおもってstd::function版を書かせたんだけど、何が解らなかったのかな? []
[ここ壊れてます]

764 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:41:13.37 ID:7dJ8iAqk0.net]
>>744
あー何となく分かってきた。以下ページ、
ja.cppreference.com/w/cpp/utility/functional/bind
の「メンバ関数 operator()」ってとこが呼ばれるのか。つか英語版見るべきだったかも。
じゃあ当初の「std::bind内部のコードもね」でも十分通じる気もするが、まあこれはいい。

いずれにしても俺はこの通り、cppreferenceの見方もよく分かってない。
だから君らに追いつくのは時間がかかる。

> コストは 直接=ラムダ=bind <<< std::function
ラムダは最高に最適化された状態でbindと同じ。
bindもoperator()の内部でプレースホルダ引数の配置をするのなら、
同様に最高に最適化された状態で直接と同じ。
結果、直接=<bind=<ラムダ じゃないか?
まあこれについてはそちらの方が詳しいだろうし、こちらも引き続き詳細確認中だが。

765 名前:デフォルトの名無しさん (ワッチョイ f35b-tpgq) mailto:sage [2017/03/19(日) 09:49:17.20 ID:7dJ8iAqk0.net]
ちなみに誰かと確認してみたが、
> std::bindを見てECMAScriptのbindingと同じものだと勘違いしていただけか。(>>688)
なるほど、その通りだ。俺が思っていたbindとはだいぶ違う。

766 名前:デフォルトの名無しさん (ワッチョイ 5319-v8EU) mailto:sage [2017/03/19(日) 09:52:16.04 ID:/fHKNSq50.net]
直接<間接=関数ポインター<λ<バインド
なぜならバインドは内部で関数ポインターを使うしかないから
ラムダは言語で実装されてるから。

767 名前:デフォルトの名無しさん (ササクッテロル Sp97-q0jq) mailto:sage [2017/03/19(日) 17:47:12.05 ID:SFAOW7ATp.net]
関数呼び出しのコストでここまで議論できるって凄いな
普段C++で何作ってんだろ

768 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/19(日) 18:17:17.48 ID:jcDR9uoj0.net]
>>750
議論ではなく出来の悪い生徒の補習してただけだから。



769 名前:デフォルトの名無しさん (ワッチョイ f37b-12+v) mailto:sage [2017/03/19(日) 18:21:02.30 ID:V1EWIlT/0.net]
ギリギリ迫るのも楽しいものです

770 名前:デフォルトの名無しさん (ワッチョイ 2302-nFTW) mailto:sage [2017/03/19(日) 18:49:00.48 ID:6JgBGVv40.net]
>>750
え、Hello worldだよ?

771 名前:デフォルトの名無しさん (ワッチョイ 7302-12+v) mailto:sage [2017/03/19(日) 20:26:30.60 ID:fEuC6OUR0.net]
ある時系列データにフィルタを通した任意の範囲のデータを扱うクラスを作るんだが
今だとイテレータよりRangeの方が良いのか?

772 名前:デフォルトの名無しさん (ワッチョイ f37b-12+v) mailto:sage [2017/03/19(日) 22:20:21.59 ID:V1EWIlT/0.net]
もう少し具体的に と思います

773 名前:デフォルトの名無しさん (ワッチョイ 8330-PVeP) mailto:sage [2017/03/20(月) 00:26:19.05 ID:V0m6X4Gc0.net]
基本的にレンジはイテレータのペアのラッパでしかなく
イテレータが無くなるわけでもないからとりあえずはイテレータを前提に作っておけばよかろ

774 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 12:05:47.42 ID:OlwkB3mR0.net]
>>737
expression templateは遅延評価による高速化のために使うんやで
速度が必要無いなら要らんのやで

>>738
実測してみた?
二項演算子(または結果を戻り値で返す関数)を多用する場合、
x, y, zを持つベクトルなんかだと明らかに効果ある
組み込み型だと全く効果ない

775 名前:デフォルトの名無しさん (ワッチョイ ef6c-i8cA) mailto:sage [2017/03/20(月) 13:05:30.60 ID:ZNh1GxS+0.net]
>>757
いつか実装して確かめてみようとは思うんだけど
・数学的に簡略化が可能な場合は当然事前にできるだけ簡略化する
・計算途中の値もよく使うので=が出てきて評価が頻繁
な場合、あんまり効果なさそうだなあというところで二の足

776 名前:デフォルトの名無しさん (ワッチョイ 5319-v8EU) mailto:sage [2017/03/20(月) 13:17:35.04 ID:hOjZeIpo0.net]
expression templateってコンビネーターのことじゃね?

777 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/20(月) 13:29:36.59 ID:o1Hy6TV3M.net]
>>758
計算途中の値もよく使うって、それ途中と違うがな
函数という考え方について、もう少し勉強した方がいい

778 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 14:06:32.00 ID:OlwkB3mR0.net]
>>758
あーまだ実装してないのね
自分の実用するコード(4次元までのベクトル、4x4



779 名前:ワでの行列)だと5〜30%くらいの向上なんで、実装する労力考えると最後のダメ押しでもよかったなとは思うけど

>・計算途中の値もよく使うので=が出てきて評価が頻繁
一応、a = b + c;程度の式でも効果あるにはある
多分インライン展開されても、レジスタの使用効率がちょっと良くなるんだと思う
a = b + c;
みたいな式で
for (int i = 0; i < 3; i++)
  a.f[i] = b.f[i] + c.f[i];
という計算に展開された方が、レジスタを使い切らないからじゃないかなと
(ちなみにループはアンロールされる前提だけど、ヒープに確保するような長いベクトルでもETの方が効率良いはず
あとこの例だと、SSEとかのSIMDのイントリンシック使うと4次元まで組み込み型になるので、全くETの意味が無くなるw)

複数の組み込み型を含む演算で、SIMDとか他の高速化を使った上でさらに速くしたいなら、ETはおすすめしたい
ただし計算過程でxがy, zに干渉するような計算(内積、外積とか)にはET使えないので注意
[]
[ここ壊れてます]

780 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 14:14:14.02 ID:OlwkB3mR0.net]
訂正
Xxがy, zに干渉するような計算
○各要素を複数回評価するような計算
a = cross(b, c);
なら大丈夫だけど
a = cross(b, c) * d;
とかやると乗算の回数が増えるし計算結果が狂ったりする

781 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/20(月) 14:25:46.95 ID:o1Hy6TV3M.net]
>>762
横から補足
ublasなんかは複数回評価を前提としてて、そのまま使うと遅い
なので、noaliasというものが用意されてる

782 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/20(月) 16:40:52.42 ID:d0t0+ba+0.net]
なるほど
よくわからん

783 名前:デフォルトの名無しさん (ワッチョイ bf0b-8YZg) mailto:sage [2017/03/20(月) 17:28:44.64 ID:lZKrgjvb0.net]
結論
expression templateは科学系数値計算にしか効果はない
そういうのは既にライブラリーが存在する
よって自分でexpression templateを実装する必要に駆られる場面はほぼない

784 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 18:08:39.79 ID:OlwkB3mR0.net]
>>765
>科学系数値計算にしか効果はない
ではなくて、「速度が必要な場面でも、実装する優先度は低い」ならわかる

自分が以前調べた限りでは、ETとSIMDを同時に使ってるものは無かった
はっきり言って、速度が重要な局面かつSIMDが使えるマシンなのにまずSIMDを使わないというのは有り得ない
けなすわけではないが、SIMD命令がある一般的なマシンにおける数値計算には、今あるETのライブラリはまともに使えんのじゃないか
ていうか科学計算ならETより、SIMDやGPGPUを使う方が先

自分の場合はゲームでの計算なんで、CPUかつヒープじゃなくスタックを使う必要があるので
その時点でuBlasやBlitzは選択肢から外れるんだわ

785 名前:デフォルトの名無しさん (ワッチョイ 7302-12+v) mailto:sage [2017/03/20(月) 18:31:45.48 ID:E6+3UOyx0.net]
あらゆる面で最適化したオープンソースな数値計算ライブラリを作るような人なんて世界でもほぼ居ないだろ
数学と物理や化学とC++での数値計算に関する造詣が深くて、処理系やユースケースを想定して形にできなければいけない
金にならないし趣味にするには地味すぎる
論文が書ければいいけどライブラリ開発自体をメインにすることはできるのかどうかよくわからんし

786 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 19:35:01.25 ID:OlwkB3mR0.net]
そういうライブラリはかなり難しいだろうね・・・
だから結局自分で作る必要があるんだわ(ETは労力やバグ回避がアレだけど、効果が無いわけではない)

787 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/20(月) 19:39:51.74 ID:d0t0+ba+0.net]
お前らの作成したライブラリを配布したらさいつよじゃね?

788 名前:デフォルトの名無しさん (ワッチョイ 537b-gO1F) [2017/03/20(月) 19:44:06.12 ID:+YHRRlIg0.net]
Eigenがexpression templateもSIMDも実装してたと思うけど



789 名前:デフォルトの名無しさん (ワッチョイ cf6b-8YZg) mailto:sage [2017/03/20(月) 19:47:48.92 ID:d0t0+ba+0.net]
お前らってコード書くとき明示的にスコープ使う??

790 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/20(月) 20:52:21.66 ID:OlwkB3mR0.net]
>>770
あーー、そういえばあった・・・・w
すまん大嘘こいてた

https://ja.wikipedia.org/wiki/C%2B%2B_AMP
ちなみにマイナーながらこんなんもある

>>771
stdならstd::つけて、それ以外ならusing宣言でよく使うやつだけ取り込むかなぁ

791 名前:デフォルトの名無しさん (ワッチョイ ef8c-h49x) [2017/03/21(火) 00:17:02.18 ID:ooaEszBV0.net]
Expression templateって右辺値参照ある今でも必要なの?

792 名前:デフォルトの名無しさん (ワッチョイ a38a-GEdz) mailto:sage [2017/03/21(火) 00:34:26.33 ID:WRmS2jUL0.net]
式テンプレートって遅延評価やそれを利用した最適化が主な目的だとおもうのだけど、それがなんで右辺値参照があるからいらなくなるの?

793 名前:デフォルトの名無しさん (ワッチョイ ef8c-h49x) [2017/03/21(火) 00:42:40.72 ID:ooaEszBV0.net]
a = b + c + d の形式の時のコピー数減らすのが式テンプレートの主な功績だとしたら右辺値参照で同じように減らせると思ったんだけど、実際それ以上の最適化ってされてるの?

794 名前:デフォルトの名無しさん (ワッチョイ 7302-12+v) mailto:sage [2017/03/21(火) 00:59:40.31 ID:/NjqKBkb0.net]
アセンブラで書くのが一番速い

795 名前:デフォルトの名無しさん (ワッチョイ f3e7-ajdi) mailto:sage [2017/03/21(火) 01:12:11.02 ID:3hTmI8gX0.net]
KoDaIJiN

796 名前:デフォルトの名無しさん (ワッチョイ bf3a-lir9) mailto:sage [2017/03/21(火) 01:44:12.85 ID:2crVP7Yr0.net]
石を焼いてしまうのが、一番早い気がする

797 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/21(火) 02:23:03.72 ID:wE8b83TD0.net]
>>775
ヒープに確保するようなクラスの演算なら、コピーのコストはそうだね(推測だけど
ただし>>761に書いたようなレジスタ効率(a.f[0]の代入が終わったらストアして以降f[0]を無視できる)もある

798 名前:デフォルトの名無しさん (ワッチョイ 33e6-8FG5) [2017/03/21(火) 03:29:49.89 ID:+DL1LwCN0.net]
>>778
それ速いけど早くない



799 名前:デフォルトの名無しさん (ササクッテロレ Sp97-GEdz) mailto:sage [2017/03/21(火) 11:41:46.69 ID:Ub2NtCH4p.net]
>>775
たとえばeigenなんかは必要な要素だけ計算されるような工夫があるようだけど

800 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 12:20:28.06 ID:ovrpZx5v0.net]
全く理解してないし、今日初めて知ったんだけど

遅延評価といっても所詮静的なものだから
こんなものはコンパイラが最適化を超がんばれ、って思う
たぶん事の本質は演算の順番を変えることで
(縦に計算するか、横に計算するか、みたいな?)
最適化がかかりやすくなったり速く動いたりできるかもね
って事なんじゃないかと俺は勝手に思った
ただ愚直に演算の順番を変えると記述性に問題が出てくるから
それを防ぐテクニックなのかなーと
よくわからないけど

801 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 12:35:09.71 ID:bH1u/9cj0.net]
Expression templateの一時変数問題は
ムーブコンストラクターで解決された問題だよね。

802 名前:デフォルトの名無しさん (ワッチョイ 737a-12+v) mailto:sage [2017/03/21(火) 12:36:27.24 ID:/NjqKBkb0.net]
プログラムが扱いやすいように初期値を設定してやるのは人間の仕事

803 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 12:54:01.22 ID:ovrpZx5v0.net]
全く理解していない俺が言うのもなんだけど
ムーブコンストラクタは関係ないと思う
演算順序を変えないことには何処かに一時的に計算結果を保存しておかないと
ダメなことには変わりないのでは?

tmp[0] = a[0] + b[0];
tmp[1] = a[1] + b[1];
r[0] = tmp[0] + c[0];
r[1] = tmp[1] + c[1];



r[0] = a[0] + b[0] + c[0];
r[1] = a[1] + b[1] + c[1];

の違いじゃないかなー

これで配列のサイズが1000とかだったらかなり差が出るんだろう
ただ、普通にforループ書けば?って気もするが
そこを演算子のオーバーロードでどうしても記述したいってのが
例の技術なのかと

俺には必要ないかなー
要素数の少ないベクトルはSIMD使うし、要素数の多い配列はループ回すし

804 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 13:04:15.57 ID:bH1u/9cj0.net]
a[0] += b[0];
a[0] += b[1];
c[0] += a[0];
c[1] += a[1];
r[0]=c[0]
r[1]=c[1]
ムーブコンストラクターを使うとこうなる

805 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 13:13:33.00 ID:ovrpZx5v0.net]
やだー
それ、aとcが破壊されているじゃないですかーー
r=a+b+c; と同等のコードになりませんよ?
あなたのは a+=b; c+=a; r=c;ですが
そもそも「+=」で破壊していく方針なら、何にも新しくコンストラクトしないんだから
これまたムーブコンストラクタ関係ないじゃないですかーー
どこからムーブコンストラクタが出てくるんですか?
もっとC++勉強してくださいよー

806 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 13:23:51.34 ID:ovrpZx5v0.net]
r = a + b + c を計算しようと思うと、これはr = (a + b) + c に分解されるだろうから
根本的に(a + b)の結果を保存しておく一時変数がいる
レジスタに配置されるかもしれないとかそういうことはおいておいて
とりあえず一時変数がいる
で、a,b,c,rがベクトルだった場合、一時変数もベクトルになる
これはあまり美味しくない場合がある、ということで
各要素にばらして要素ごとにr = (a + b) + cを実行する
そうすると一時変数はスカラーになる
しかし記述性に難が出るので、それを何とかしようとした

↑これが基本的な要点かと

807 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 13:29:00.21 ID:bH1u/9cj0.net]
間違えた
tmp[0]=a[0] + b[0];
tmp[0]=a[1] + b[1];
tep[0]+=c[0];
tep[1]+=c[1];
r[0]=temp[0]
r[1]=temp[1]
一時変数が一個で良いってことだな
aかbが右辺値なら1個だ

808 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 13:30:57.12 ID:bH1u/9cj0.net]
また間違えた、aかbが右辺値なら0個だ



809 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/21(火) 13:32:10.85 ID:wE8b83TD0.net]
>全く理解していない俺が言うのもなんだけど
どこが全く理解していないのかと小一時間w

ただムーブ代入演算子やコンストラクタがあれば、”ヒープに要素を確保するクラス”限定で
ヒープ確保や代入命令のコストがポインタのすげ替えだけで済むのはある(>>779

でもスタックに確保するような固定長のベクトルとかだと、>>785の通り代入命令の回数が
バカにならないので結構差が出てくる
「C++の演算子オーバーロードは遅い」なんて言われることがあるけど、その理由がこれだと思う
演算子オーバーロードが遅いんではなく、計算結果を戻り値で返す関数が遅い
(これは計算結果を保証するためなのかどうしようもないんだろうけど)

なのでそれを回避するために算術代入使おう、という論もある

ただし遅いと言ってもFortranとC/C++の差のレベルなんでアレだけど・・・・
多分愚直な演算子で書いても、全てインライン展開されれば最適化でベストなコードになると思うんだけど・・・(誰か知ってる人頼む

810 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 13:32:18.98 ID:bH1u/9cj0.net]
もう一個訂正tmp =temp,tem,tmp

811 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/21(火) 13:37:29.55 ID:wE8b83TD0.net]
>>789
右辺値についてだいぶ誤解してないか?
ムーブコンストラクタ/代入演算子は引数が右辺値である場合の実装を分けられるだけやで

812 名前:デフォルトの名無しさん (ワッチョイ 534f-v8EU) mailto:sage [2017/03/21(火) 13:41:08.81 ID:bH1u/9cj0.net]
実際に
tmp[0]=a[0] + b[0];
tmp[0]=a[1] + b[1];
tep[0]+=c[0];
tep[1]+=c[1];
r[0]=temp[0]
r[1]=temp[1]
上のと同等の演算が
r[0] = a[0] + b[0] + c[0];
r[1] = a[1] + b[1] + c[1];
で出来るというわけで実際に
3回に計算するわけじゃないよ

813 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/21(火) 13:41:36.76 ID:wE8b83TD0.net]
訂正
Xヒープ確保や代入命令のコストがポインタのすげ替えだけで済む
○最後の代入演算子で発生するヒープ確保や代入命令のコストがポインタのすげ替えだけで済む
a, b, cの演算結果は依然としてコストあるね

814 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 15:17:50.73 ID:ovrpZx5v0.net]
そーゆーことでしょうな
むしろ内部でstd::vectorとか使ってベクトル表現している方が
要素ごとにバラして計算するメリットが出るだろうね
計算途中の一時変数がstd::vectorになるのとスカラになるのとでは
全然違うというか話にならないからね

あと
> ○最後の代入演算子で発生するヒープ確保や代入命令のコストがポインタのすげ替えだけで済む
だけど、たぶんだけどstruct vec{ int x,y,z; };みたいなやつだと
最後の代入はコンパイラの最適化で消えてなくなるだろうから気にしなくてもよいはず
C++にmoveホゲホゲが出来る以前からあった古来からの基本的な最適化だったはず
まぁoperator=を定義して余計なことしてたらその限りじゃないかもしれんが

815 名前:デフォルトの名無しさん (スプッッ Sddf-8YZg) mailto:sage [2017/03/21(火) 16:21:56.57 ID:rDA5FTfNd.net]
umdhの結果でleak検索して出てこなかったらメモリリークしていないって判断して問題ない??

816 名前:デフォルトの名無しさん (ワッチョイ f33c-u6wT) mailto:sage [2017/03/21(火) 18:56:32.83 ID:wE8b83TD0.net]
>>796
RVOのことかな?そういえば完全に忘れてた・・・
確かoperator =を定義していようが副作用があろうが、コンパイラは勝手に
コンストラクタや代入演算子の呼び出しを減らしていい、って感じだったと思うんだけど
もしかして同じ機能のコンストラクタがあるならoperator =は無駄??

817 名前:デフォルトの名無しさん (ワッチョイ bf90-tpgq) mailto:sage [2017/03/21(火) 22:33:32.67 ID:QxtkUNUp0.net]
map<T,U> map;
とか
for (auto pair : map)
というのをつい手癖でやってしまうのですが
こういう名前の付け方はやめたほうがいいですか?

818 名前:デフォルトの名無しさん (ワッチョイ 336e-8FG5) mailto:sage [2017/03/21(火) 22:47:54.58 ID:ovrpZx5v0.net]
大前提としてチームで開発しているならチームのリーダーに質問してください

自分一人で書いてるなら変数名なんかなんでもよいよ
自分で書いたコードでも一年たったら他人が書いたコードのように読めない
っていう人もいるけど、実際には普通に読めるから変数名は思い付きのテキトーでよい
型名をもじってそのまま変数名にするってのは俺もよくやる

実際変数名は本当に何でもよくて
なぜならスコープが狭かったり、クラスのプライベートメンバだったりして
ごちゃごちゃになったりしないから
問題はクラス名と関数名で、こちらはいつも悩む



819 名前:デフォルトの名無しさん (ワッチョイ bfcc-UNkP) mailto:sage [2017/03/21(火) 22:53:34.07 ID:BqDV4BtF0.net]
やめたほうがいい
あとあと混乱するから

820 名前:デフォルトの名無しさん (スップ Sddf-Ma5U) mailto:sage [2017/03/21(火) 22:53:51.11 ID:chOyeLILd.net]
あとはインタフェースの一部としての引数名かな。
総じて.cppファイルにだけ書かれる名前はテキトー

821 名前:デフォルトの名無しさん (ワンミングク MM5f-W3uL) mailto:sage [2017/03/21(火) 23:38:01.75 ID:XhVovTkQM.net]
>>799
mapはデータ構造だろ
変数名はそれが何を格納してるかを表してなきゃダメだと思うけど

822 名前:デフォルトの名無しさん (ワッチョイ 03b4-w0Gz) mailto:sage [2017/03/21(火) 23:45:02.12 ID:5oluTi0x0.net]
>>803は健常者

823 名前:デフォルトの名無しさん (ワッチョイ bf90-tpgq) mailto:sage [2017/03/21(火) 23:57:16.03 ID:QxtkUNUp0.net]
>>800-804
ありがとうございます。くだらぬ質問でしたね、すみません
とりあえず狭いスコープの一時変数用途では
map<T,U> m;
for (auto p : m)
みたいにしておきます

824 名前:デフォルトの名無しさん (ワッチョイ 3fd1-q0jq) mailto:sage [2017/03/21(火) 23:59:23.77 ID:eniBTwk40.net]
やめた方がいいですか?なんて聞いてる時点で本人の中でも既に答えは出ているのでは

825 名前:デフォルトの名無しさん (ワッチョイ 737a-12+v) mailto:sage [2017/03/22(水) 00:10:41.47 ID:kq8u5G9J0.net]
使い捨てならアンダーバー付けろ

826 名前:デフォルトの名無しさん (ドコグロ MM57-3fK7) mailto:sage [2017/03/22(水) 06:47:53.98 ID:svIchgSfM.net]
>>799
どちらもスコープが狭ければいいと思う
特に pair の方は for 文でよく使われる i みたいなもんだから俺もよくやる
map の方はたいていスコープも広いし中身を表す名前にした方が分かりやすいと思う
型名と同じ名前はどうよ?
って話なら俺個人的には問題ないでしょって思うけどそう思わない人の方が多いような気がする

827 名前:デフォルトの名無しさん (ワッチョイ f384-ajdi) mailto:sage [2017/03/22(水) 07:01:10.32 ID:2VeNeFOl0.net]
for(auto&o : c)て感じでやってるなぁ。
oはobjectのo。

828 名前:デフォルトの名無しさん (スップ Sddf-rwfr) [2017/03/22(水) 07:36:14.20 ID:BzP+Rc7Ad.net]
変数名に型情報をのせるなマイクロソフトじゃあるまいし



829 名前:デフォルトの名無しさん (オッペケ Sr97-w0Gz) mailto:sage [2017/03/22(水) 07:43:37.16 ID:l4RQ+gMQr.net]
別にのせてもいいけど、型でしかその概念

830 名前:捉えられない人にマトモな設計は難しい
int intTypeVar=-1;
[]
[ここ壊れてます]






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

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

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