|
プログラマを営んでいらっしゃる平山さんからのお便り。
はじめまして、プログラマをやっている平山と申します。
ホームページのPrejudice、楽しく読ませていただいております。プログラム
のことについて、読んでいて色々考えたことがあったので、ぜひにと思いメー
ルを送らせていただきました。
長文になりますのでお暇なときにどうぞ。すでに解決済みのこともあるかと思
いますが、どうぞよろしくお付き合いください。
---971108について
STLについてご存知なのでしたら、もしかしたらもうわかってらっしゃること
かもしれませんが、あなたがPrejudiceに書かれた「ストラクチャ・プール」
は、アルゴリズム的にはまさにSTLで使われている"allocater"そのものです。
そいういうわけなので、固定長のオブジェクトなら、速度を気にするとしても
listテンプレートを使ってOK(のはず)です。標準性から言えば、積極的に使
うべきでしょう。
ただし、ベンチマークを取ってみたわけではありませんので、もしかしたら駄
目かもしれません。機会があったらやってみることにします。今までの経験を
踏まえての予測としては、アルゴリズムよりインライン関数の最適化のほうが
問題になるような気がしています(VTuneについてくるIntelのコンパイラはかっ
こよくやってくれるそうですね)。
もしうまくいかなかったら、STLのコンテナはどれも別のallocaterを第2テン
プレート引数として受け入れることができるようになっているので、そこに自
作のアロケータを渡せばいいと思います。それでだめなら、それはもうテンプ
レートを使うのがそもそも駄目ということになるでしょう。
……という仕組みが分かっていれば、読むのもそれほど難しくないはずです。
STLに片方向リストはないので、両方向listのオーバーヘッドが気になるなら
片方向listを作ったりするのも面白いかもしれませんね。
listではありませんが、私も昔STL互換のコンテナを一つ作ったことがありま
す。よければご覧になってみてください。アドレスは
http://www.jah.ne.jp/~naoyuki/
です。
---971109について
C++の言語機能の効率については、「C++/Cプログラム改善法」(D.スプラー著、
トッパン、ISBN4-8101-8560-5)という本に詳しく書かれています。時間があっ
たら読んでみると面白いかと思います。例えば、仮想関数については、「仮想
関数は速くはないが、同じことを別の方法で実現することを考えればそのコス
トはかなり安い」と書いてあります。これはあなたの結論と同じですよね。
--971114について
上で書いたように、STLのコンテナは「オブジェクト・プール」に相当するメ
モリ割り当て機能を持っています(いるはずです)。
Prejudiceを読んでいても思ったのですが、一般にC++の提示している姿勢は、
オブジェクト指向業界というかそういう感じのところで軽視されすぎているよ
うに感じています。C++のテンプレートの真価は、静的にバインディングされ
るために実効効率のよいコードが生成される点ではなく、丁寧に利用
するとうまく直交的な設計ができる点にあります。STLはこの点で非常に有用
なのです。
LISPのCLOSや一部で話題のruby(さらによく知りませんがおそらくSmallTalk
も)のような型付けの弱い言語なら、似たようなことを動的なバインディング
でできますが、型付けの強い言語ではこれがないと相当みっともないことにな
ります。私がJavaを好きになれない理由はこれなのです。
同様に、演算子のオーバーロードの真価は、string s3=s1+s1みたいな式が書
ける点ではなく、メソッドのマルチプルバインディング(*1)ができる
ことにあります。ストリーム演算子(<<、>>)はこれを利用しています。これ
があるおかげで、型付けの強い言語でも「メソッドの後付け」ができるのです。
テンプレートでも近いことができます。但しすべて静的にしかバインドできま
せんが。
*1 ご存知かも知れませんが、複数のオブジェクトを利用して実行時にバイン
ドされる関数を決定する方式をいいます。普通のメソッドは一つのオブジェク
ト(this、selfみたいなもの)を使ってバインドする関数を決定します。
今のところはまだ、テンプレートメンバ関数を使えるコンパイラがないなど、
なんとなく不自由なところがありますが、今後こういう細かい不自然な点が修
正されていけば、相当いい感じになるのではないかと考えています。
もちろん、最終的には思想はそのままで下方互換性を捨てて「D」言語にして
欲しい、とも思いますが。
多重継承が目の前にちらつく局面でも、たいていの場合templateでカバーでき
ます。というより、templateがあれば多重継承は要りません。事実私は多重継
承を自分で使ったことがありません(これはそういう方法で分析してるからで
もありますが)。
要するに何が言いたいのかというと、よく「変」とか「汚い」とか言われるけ
ど、違った角度から見てよくよく吟味してみるとそれほどでもない、むしろ他
の言語のほうが変ということも多々ある、ということなのです。C++プログラ
マがいちいち反論しないのは、あなたのページからのリンクで行ける「kill
mac」ページで書かれていたような、WindowsユーザとMacintoshユーザのよう
な関係であると考えたほうがいいような気がします。
……といってもこの辺は自分でもそんなに自信がある部分ではないので、こう
いう考え方もあるということで。
STLについては、「C++エッセンス」という本に大体の使い方が書かれています
ので、もし必要であれば参考にされるとよいかと思います。私はCマガジン、
DDJなどの雑誌の記事で覚えましたが、すでに持っているのでなければ入手は
困難でしょうから。
---971118より
rc_ptr(リファレンスカウントポインタ)を実装してみました。まあプロトタ
イプは1年以上前からあったのですが。よければご覧になってみてください。
一応実戦にも投入して検証中です。今のところいい感じで動いています。
今のところ言語仕様上しょうがないところがあって、キャストの構文がみっと
もなかったりしますが。早くメンバ関数テンプレートが使えるようになるとい
いんですけど。それで困ってるところがこのモジュール以外にもいくつもあり
ます。
先のURLに置いてあります。
---970418より
まさにその問題を解決する構文が、gccにはあるらしいです。この辺のページ
をご覧になったことはおありでしょうか。
http://www.bekkoame.or.jp/~bero/gnudocj/gcc/gcc_9.htm#SEC98
もっとも、これがANSI C++に採用されるとは考えづらいので、結局使うわけに
は行かないと思いますが。
妥協策としては、+=演算子をオーバーロードするという手も、場合によっては
使えると思います。
もうちょっと複雑なクラスだったら、copy on write、さらにもう一歩踏み込
んで使用時計算方式にする手もあるんでしょうが、この手のちょっとしたクラ
スでそんなことをしたら、オーバーヘッドのほうがでかくなってしまいますか
らね。
-----
といったところで。
これからも頑張ってください。楽しみにしています。
そうそう、よかったら相互リンクしませんか。
シグネチャの下のほうのアドレスで。上でも構いませんが。
平山直之
hirayama@fujiyama.jpn.org
http://www.p-k.com/bthrough/
http://www.jah.ne.jp/~naoyuki/
|
やっぱりなー。あると思ったんですよねー。ストラクチャプール的なやりかた。
で、それはまさにallocatorというテンプレートとしてSTL(スタンダードテンプレートライブラリ)に入っているそうです。
STLは書店でざざざっと流し読みして調べただけですので見落としてました(allocatorという言葉自体初めて聞きました)。いやぁ、無学は罪ですね。しかし半年間誰も指摘してくれなかったのはショックです(笑)
しかしまぁ、STLってやっぱ内部にゴチャゴチャっとあって、あまり使う気がおきないというか、なんというかMFC的というか、ちょっと引いちゃうものがありますね(俺だけかな)。リストにしても、STLのリストだとやっぱり数珠つなぎ問題は解決できないようですね。それにやっぱり融通効かなそうというのが引いちゃう理由その2ですな。
ドキュメントが整備されてないこともありますけど、どうも「なんだコリャ」という部分が多い気がします。イテレータテンプレートっていうアイディアとか、凄いなって素直に思うんですけど、実際使うとなったらどうかなって言うか、やっぱアイディアだけ頂いて自分で作った方がいいかなと思います。
なにより、STLのヘッダを探すのがちょっと面倒なんですよね。VisualC++のINCLUDEディレクトリから。拡張子ない奴とひとくちにいっても、結構あって、基礎知識がないからどれがどれやら・・・・。
それに、ストラクチャプールとかってやっぱりゲーム的な一種の専用感漂う、ソフトウェア工学的にはダメな手法だし、そういうダメな奴は自分で面倒みたい気がします。
というのも、そもそもゲームってソフトウェア工学的(?)にはそれほど嫌がられていないmallocの仕組みそのものを全く使わないことが多いし、事実使わない方が効率的なので、それならメモリ管理もイチから自分で組んだ方がすがすがしいですよ(笑)。
いや、無論、僕も一生ゲームなんか作っていたいなんて微塵も思っていないんですが、だからこそSTLはちゃんと勉強しておかないとやっぱ駄目なんでしょうけど、そのことといま使うかどうかという問題は別ですね。
とても勉強になりました。
本当なら、こんな泥臭いことやんなくてももっとmallocでエレガントに処理してもらえたら、それはそれで幸せなんですがねぇ。
だれか、フラグメンテーションが発生せず、検索コストもかからないmallocを考えてくれると良いんですがそれって宇宙的ですらありますね。
今のところ一番有望なのは、やっぱりページングによる4KBパラグラフ単位の再配置でしょうか。これならあたかもディスクにファイルを書くようにメモリを効率的に使えるのでバンバンザイですが、残念ながらページングをそのような目的で使うには、いまのOSはあまりにズサンですな。
それともVirtualAlloc関数はちゃんとページングしてフラグメンテーションを解決しているのかな(してそうだ)。しかしVirtualAlloc関数はあまりに遅い。なぜ遅いんだろう。タスクスイッチのせいだろうか。解せないなぁ。
Javaチップはガベージコレクションをどうやって解決しているのか、気になるところでありますね。時間をみつけて調べてみましょう。
|
|
|
|