2009-11-2[月]実は仕事辞めました。 正確には今月末なんですが。 で今日は送別会してもらいました。 今までありがとうございました>職場。 プレゼントのPSPGOはわりと(ry。
2009-11-20[金] go言語
話題のgoogleのgo言語、おもしろそうですね。
とりあえず、確かにC言語系だけれど、perl以上に似ていない。 でも、javaやC#が、C/C++ユーザーの習慣に妥協した、 型宣言やビット演算子の順位等の'不味い仕様'の部分にも手をつけていて、 基本的な部分での記述量を減らす工夫が多々あり、
C風というには、あまりに思い切りがいいです。結構好みです. ビットクリア演算子は、ビット演算が敬遠されるご時勢にいれてくるのは、 執念か何かでしょうかね. 関数の他値返しも今風だけれどタプルなんてクッションも無く... アセンブラからCに移った人のボヤキがよみがえってきたり.
プログラムの分割については、 公開/非公開の制御を classベースでなく package ベースのみ、ってのもばっさり感があり. 指定方法が、名前の先頭文字が、 大文字なら外部(public)公開、小文字なら内部(private)、 というネーミングルール強制というのもそうだし. 構造体メンバー変数についても、構造体固有のアクセス制御ができないだけで、 メンバー変数名の名前の大小文字で、packageレベルでは行われる。 もちろん同一パッケージ内の他の関数からも丸見えですが、 このへんはD言語での同一ファイル内の非メンバー関数をfriend扱いするのと同じ考え方でしょうね. パッケージの規模を大きくしすぎず設計しろよ、ってことで.
クラス関係は C++やjava等のclassがもつ(継承とかの)強力さをあえて抑えることで、 必要以上に強力な機能を濫用して発生してた複雑さを軽減しようって感じでしょうか. 継承はないけど struct のメンバー関数は、struct宣言と同一package内なら 別ファイルでも宣言できるので、既存のパッケージのstructの拡張がわりと容易のよう.
... と、まあ、見てるとわくわくするのですが、
なあたりで、様子見な感じになってしまうのでした. (例外が無いのは個人的にはok)
ちょこっと弄ってみましたが、 package のコンパイルは、 同一packageのソースはコンパイラに一度に指定する 必要があるぽい。 6g foo.go foo_sub.go 逆に違うパッケージは一緒に指定しちゃダメ. 生成されるオブジェファイルは .o 等と違い go 固有の情報を含んでるみたいで import "foo" で参照されるファイルはソースじゃなくて .6(.8) のよう. なんで、依存関係を考慮した順番にコンパイルしないとダメかも... D言語での rebuild や bud 相当のツールがほしいところです. GCCベースのほうはどうなのかは未見.
2009-11-23[月] ひさびさにD言語
ひさびさにD言語を触ってみました。
まあ、Goの影響です:-)
ただ問題はデバッガ. とりあえず dmd2 2.036, dmd1 1.051 入れて、
Ddbg
Ddbgは本家のダウンロードページにある
v.0.11.3beta をダウンロード。 普段はIDEから使うだろうで、その場合は大丈夫でしょうが、 一応、dmdコンパイル・デバッグ時に pathの通ってるフォルダに インストールしておくのが無難な気はします. (というか以下、パス通した状態で設定してるので、下記ideの設定で パス抜けの可能性もなくはなく) Eclipse+DescentEclipse+DescentでのD環境は、Descent本家とかこのへんとか見ながら設定. 試してみると、EclipseのC環境(cdt)とかに比べるといかにも無理やり間借してる感じで、ちょっとわかりにくいです。 IDE本来の設定項目名の場所でなく、 外部ツールとしてdmdリビルドツールを登録、という形になるので、 ソース依存関係や構成の管理はIDE側じゃなく、 登録するツール任せ。 なので、RebuildやBud等のD専用リビルドツール使うのがベターってことのよう (面倒でよければ自分でmakeなりバッチなり書くのでも). デバッグ実行は、生成されたexeファイルの右クリックメニュー の'デバッグ'の中のAplication1とかを実行. (他のメニューのデバッグを押してはだまされたり:) eclipse自体に慣れていないので、適切かどうかは別として なんとかデバッグ実行できるようにはなりました。 で、一応、
ができてそこそこな感じなんですが、 ウォッチ・ポイント(データのブレークポイント)が貼れない... Ddbgのコマンド一覧見ても(またソースでgdbのwatchコマンド探しても) 無かったので、Ddbg自体が未対応のようなんでしょうね。 他にも変数表示がおかしい場合があるとかバグもちょこちょこあるようで、 あともう少しなんとかなってほしい感じなんですが... Ddbgの開発一年以上とまってるぽいのがなんとも残念.
Code::blocksCode::Blocksはdmd対応なんで、 最初からほとんどそろってますが、dmd実行パスとかデバッガ(ddbg)の 設定等、やり直してあげる必要が何箇所かあります。 (以下、dmd自体はデフォルトのc\dmdかc:\dmd2にインストールされているものとして)
また、使用したnightybuildの場合、D1,D2用2つのパス設定が かかれてましたが、 実際に登録したdmd.exeに対応する版のみにして使わないほうは削除.
さすがに対応ソフトなので、素直に操作できます。 最初、変数表示が watch(監視)ウィンドウで行えることに気づけずてっきりないのかと はやとちりしてましたが、あったので安心. (IDE ドッキングできていい感じ). (ただ watchpoint=データ・ブレークポイントは, ブレークポイント・ウィンドウで 設定できますが、Dではやっぱり機能していませんでした) winでD2したかったので dmd + ddbg でしましたが、 D1でよければ gdc + gdb(gdc対応?版) という選択もあり... 面倒なんで手がまわりませんが。 ldc とか D.net とかもあって、どんな感じになってきてるのでしょうね. D.netは、以前試したときは、 D.netコンパイラ自身のコンパイルはすんなりすんだけど、 .netの事情わかってないので (単純すぐにvs環境で使えるわけじゃないようで) リッチなのかプアなのかよくわからず.
2009-11-26[木] 〔D言語〕Ddbgの再コンパイルDdbg(Descent,CB)を使って変数表示がおかしくなるのは、 どうも Ddbgコマンドの lsv が使われた時みたい... なので、そこそこ状況限定されるから、なんとなくバグとれそうな 気がしてしまったで、 ソースのsvnリポジトリr1094 をみると実は公開exe(v.0.11.3)よりも新しいv0.12(2008-3-26)のソースがコミットされているようなのでした。 (コミットログにはbasic hardware breakpoint support-minor changesと) で、とりあえず Ddbg をコンパイルしてみたのですが... そこはD言語、やっぱり泥沼にはまったのでした。 Ddbg 自体はD1で作られていて、 最新のD1でコンパイルしても今まで見過ごされていたバグが 検出される程度(すぐ修正可能)だったのですが、 問題は、bud とパーサージェネレートに使われてる Apaged.
budはエラーがでるため、apagedは配布サイトにソースしかないため、
ツール自体の再コンパイルを行ったのですが、まさにドツボ。 結局、budについては、ソース構成割り出してバッチで処理, apagedに関してはふと apaged.exe を検索したらこちらで見つかったので それを用いることでなんとか. ただ apaged 自体の文法に変更があったり、 ジェネレートされたルーチンの関数引数が変わってるため Ddbg側もそれに合わせて必要だったり、と結構疲れました. あと win32 bindingも、今のdmdだと依存関係でひっかかり、ちょっと嫌な修正. udis86-1.4部分もたいしたことないけど (こいつも perl でソースジェネレートとかあって、それをさけるため) makefile若干弄ったりとか.
で、肝心の Ddbg lsv のバグですが、
StackSymbol[] locals_args = scope_sym.symbols.stack_symbols; auto psym = cast(ProcedureSymbol)scope_sym; if ( psym !is null ) locals_args ~= psym.arguments.stack_symbols; foreach ( sym; locals_args.sort ) {
の部分で、関数内ローカル変数一覧に関数引数変数を追加して
ソートし出力してるのですが、locals_args がコピーでなく実体
を指しているため、追加&ソートにより scope_sym.symbols.stack_symbols が
破壊されてしまっていたようです. とりあえず .dup つけて StackSymbol[] locals_args = scope_sym.symbols.stack_symbols.dup;
で直るよう.
弄った Ddbg をさらしておきます. [download]
ついでにbudのバグもメモ.
文字列インポートとしての import("file.txt") に未対応のよう. source.d の void doImport (in string pFileText, inout int pPos) 中の
bool first = true; //@@@ while ((lSavedPos = pPos, lCurrentToken = GetNextToken (pFileText, pPos)) !is null && (lCurrentToken != ";")) { if ( lCurrentToken == "(" && first) return; //@@@ first = false; //@@@ if ( lCurrentToken == ",")
のwhile付近に //@@@ の処理を追加すればとりあえずなんとかなるぽい. (自分のコンパイルしたexeを使って出るエラーの原因が不明なんでexe無)
と書いててて思い出した.
dmd自体の仕様変更かバグかしらないけど、
ddbg の再コンパイルではまった件として、-Jsrc 状態で import("cli\ddbg_help.txt") が使われてもソース無いって起こられてた.
2009-12-2[水] Unicodeコンソール関係の適当メモunix/linux系なら、過去互換気にしなければ普通utf8環境. winだと一応(たぶんnt系. 少なくともw2k以降の) dos窓にて chcp 65001 とすれば、文字エンコードをutf8にした環境に (あるいは chcp 65000 とすれば utf7環境に) はなる.
ただし、文字フォントが日本語ファイル未対応なので、そのままだと文字化けする.
こちらのサイト等みて
レジストリ設定すれば日本語表示可能になる.
で表示はなんとかなるが、問題は、日本語入力(IME)が使えない. 日本語環境とみなされていないよう. CP932でのみ判定してるのか、DOS標準コマンドのヘルプが英語になる. (当然sjis依存ツールは文字化けなんで、それに比べれば十分マシだけど). os標準の入力(MS-IME)が出来れば、もっとutf8コンソール普及するかも? (Win7は未確認だけどたぶん)
utf8環境での、言語(国)の判定は win32apiだと LCID GetUserDefaultLCID(); で判定可能。LCIDでの日本は1041. (他にも何か判定方法はあったような気はするけど、これが楽かも.
C標準ライブラリの場合 setlocaleはあれど getlocale なんてのはないので標準的な判定はなし.
(そもそもsetlocaleの引数/戻値はosによって設定する値が違うので、移植性を考えよう無い)
unix系だと環境変数LANG みれば... iconv とか gettext とか用いるが普通?
オーソドックスなコンパイラなら、ソース中のマルチバイト文字(というかSJIS)対応をするオプションを立てずにutf8でソース書けばok (のはず).
winでsjisコンソールのままプログラム内部の処理をutf8にした場合 問題になるのは
あたりか. もちろん通常プログラムが扱うテキストファイルはutf8でいいとして. このためにCランタイムやライブラリを修正するとしたら、 コマンドライン引数はW系文字列で取得してutf8化すればすむだろうが、 対コンソール入出力についてはどうする? 標準入出力関係だけならば、fileno(fp) が 0,1,2 なら標準入出力エラー出力だろうで、 決めうち変換する? (freopenとかやられると不味いそう?) win系コンパイラ(vc,mingw,dm,bcc,watcom)ならio.hにfileno(),_get_osfhandle()があるだろうで、 FILE fp = stdout; //fopen("hoge","rb"); int fno = fileno(fp); HANDLE hFile = _get_osfhandle(fno); DWORD type = GetFileType(hFile); として type == FILE_TYPE_CHAR ならコンソールだろうとして、扱えばいいか (LPTは微妙) コンソールのコードページ判定は GetConsoleCP(); // コンソール入力のコードページ GetConsoleOutputCP(); // コンソール出力のコードページ でできそうなので、utf8(65001)以外ならその文字エンコードに変換してから出力すれば... FILE関係, io.hな_open関係 にごっそり手を入れる必要があるのでやってられないけど(可能性としては).
utf8化することでSJISに対し
が、SJIS(DBC)だと基本的に 1バイト文字は半角、2バイト文字は全角、になるので
固定フォントによるテキスト表示をバイト数で桁あわせできて楽だったのが、utf8だと、単純にできなくなる.
ただ日本語フォントかつ SJIS範囲の文字のみを前提に決め内するならば,
で扱うのでもいいかも. 欧州系の文字の場合半角扱いのフォントのほうが多いだろうけど、 JIS第一水準のギリシア・ロシア文字あたりは、日本系のフォントなら全角だったりして、その判定は 結局フォント別に判定が必要になってくるかも...なので、あくまでJIS漢字の範囲を前提にするならばこの程度でよいかも、と.
vcの場合fopen("hoge", "rb,ccs=UTF8")やopen("hoge", _O_RDONLY|_O_UTF8); のようにオープン時にutf8(同様にutf16)指定することが可能なよう.
D言語環境とか、mingwでの文字列をutf8ベースにする場合とかを考えてた. mingwの場合、msvcrt.dll系のdllを使うので、ライブラリ関数一部差替は ヘッダ弄ってimportやめてリンクする形できるだろうが... あるいは newlib 使ったバージョンとかはないのだろうか... とか何かと大事な作業に化けてしまうので、思うだけで終わってしまったのでした.
2009-12-4[金] pyukiwiki(0.1.7)のrss10プラグインがmixiで使えていなかったmixiの日記設定でここを登録していたのだけれど、結構前からrssが反映されなくなっていた。以前は反映されてたのに. この機会にちょろちょろ調べてみたところ、 こちら にらしい情報が... mixiのヘルプ見返したら、たしかに http://www.feedvalidator.org/ でチェックしろ、と. で、どうやら <dc:date>2009-12-03T00:00:00+9:00</dc:date> 等の+9:00が+09:00でないと駄目なのか? 共同開発版 pyukiwiki 0.1.7 のrss10.pl をみると該当箇所は my $date = $1 . "T" . $2 . sprintf("%+02d:00", $gmt); となっていてちゃんと02dじゃ...いや +がついてるから+-のための桁も必要で "%+03d:00" にしないと駄目なんだろうな(perlはよう知らんがcではそうなので) 修正して試してみるとあたりだったよう. とりあえず、無理に日記移転とかする必要はなくなったかな.
2009-12-9[水] ググれるようになった
自分のサイト/ページがググって出てくるのってやっぱ嬉しいな.
2009-12-10[木] C標準ライブラリのマルチスレッド対応のメモグローバル変数や関数内部のstatic変数、あるいはそれらにアクセスする関数は、 複数のスレッドから同時に読み書きが行われると破綻する(バグになる). C標準ライブラリで(特にマルチスレッドセーフに作っていない場合)そのようなものは
等結構ある.(malloc関係はちょっと別枠だけど)
マルチスレッド対応の方法としては、たとえば元が static unsigned long rand_seed = 1; int rand(void) { rand_seed = rand_seed * 1103515245L + 12345; return (rand_seed >> 16) & 0x7fff; } て感じだとすると, 雰囲気として
struct ThreadLocalVar { // この構造体は適当 long rand_seed; // rand,srand char* strtok_ptr; // strtok char tmpnam_buf[_MAX_PATH]; // tmpnam int errno_wk; // errno : (その他標準ライブラリが使う変数全部) : }; ThreadLocalVar* get_threadLocalVar() { return 現在のスレッドのThreadLocalへのポインタを返す; } int rand(void) { ThreadLocalVar* p = get_threadLocalVar(); p->rand_seed = p->rand_seed * 1103515245L + 12345; return (p->rand_seed >> 16) & 0x7fff; } といった感じに、ライブラリが内部で使う変数すべてを収めた構造体を用意してスレッド別にそのメモリを持つ. スレッドごとに独立して処理するため、他スレッドの影響が起きないようになる.
当然、スレッドの開始時にはこの構造体の初期化が必要になる.
あと、上記では、適当にget_threadLocalVar()の名で中身はしょってるけど、
vcだと_getptd()、 ようは、スレッド別のメモリのポインタの取得は、 グローバル変数アクセスごとにmutex等で制御したりするのに比べれば まま軽いだろう(そこまで非効率な実装にはなってなかったよと).
ただ strtok のような本来十分に軽い処理からすれば
(そうであることを前提に利用頻度が高い場合)、
スレッド別のメモリのポインタの取得は気になるかもで、
可能なら使わずにすます形にしていったほうがよいだろう.
C++0xではスレッドローカル記憶域(TLS)が追加されるかもらしい.
そういやD言語ver2もサポートしてる. D2の場合は特に指定のないグローバル変数はスレッドローカルになる.
2009-12-12[土] ソートはPGの基礎知識...昔(もう20年ほど前か)、os-9/6809を使っていたときアセンブラで dirコマンドを自作してソート機能をつけたことがある。 このとき最初 単純にかける(O(n^^2^^)系の)ソートで 実装していたのだけど、 公開してみたら、遅いからクィックソートにしてみたら、 と言われたのだった。 実際、差し替えたところ、 十数秒かかっていたのが3秒ぐらいになって、非常に驚いた覚えがある。 アセンブラでカリカリに書いてるから速いつもりだったんだよ。 でもそれ以上にアルゴリズムの性能が段違いにモノをいう、 ってのを身をもって教えられたのでした。 まあ、ものわかりの悪い奴なんで、 実際に経験しないと気づけないという... 本に速いと書かれているのみてても、その性能差を汲み取れてないのよね. その後、情報処理専門でない理系の大学のプログラムの授業で ソートを習ったりしたので、PGならソートくらいは知ってて当然の つもりだったのだけど... 数年前、作るものの仕様に整列をする部分があって、 やたら見積もり時間がおおかったり難色しめしたりする子がいて、 聞いてみるとソートを知らないという。 ゲーム専門学校とはいえプログラマ・コースだったから てっきり知っていると思ったら習ったことない、と。 初めてコレ聞いたときはかなりがっくりきた。 その後ゲ専出の何人か聞いた範囲ではほとんどが習ってなかった。 習っていた子もいたけれど、 バブルソートを自分で書いたことがある程度で、 でもって、ちゃっかりそのルーチンを仕事の実機で書いてくれて、 非常に残念な気分を味わえたのだった。(己と同じ過ちを...) これが酷いのか普通なのかはよくわからないけれど... ソートに関しては、 簡単だけれど性能の出ないルーチンを下手に作らせるよりも (PGは自分が書いたルーチンを使いたがるものだから)、 アルゴリズムの違いの性能差をとっとと見せ付けておくほうが、 そして、標準ライブラリにはそれらを使ったstd::sort(なりqsortなり)が あることを知ってもらっているほうが、いいだろうと思う.
ソート時間を測定してみる.ということで、かるくソート時間を計測してみとく. 実行環境は Athron64 X2 5600+ 8GB(Vista64) と Crusoe TM5400(600MHz) 256M(Win2k) なマシン. テストしてみたルーチンはコレ. 元ネタはwikipediaやその他検索ひっかかった所から.(面倒なんでクィックソートとか単純なまま) バブル,選択,挿入, コム, クィック, クィック+挿入(閾値32), std::sort, qsort の時間をチェック. (std::sortを呼ぶためC++でコンパイルしてるけれど他はCでの記述状態)
適当な個数のソートを何回か繰り返した平均を出している。 テスト環境は普段使っているPCのまま。 なるべく他のソフト立ち上げていないけれど、エディタやファイラは 多少残してたり常駐ソフトも残ってるしで、厳密さはなし。 時間計測も単純にC関数のclock()に任せてるので精度とかは微妙かもだし。 測定しなおすと、細かい数字は結構かわるし、たまに当たり所が悪いと余計に時間 食っていることもありそうだし。
それでも、大雑把な傾向は出てると思う.
Crusoe TM5400(600MHz) 256M(Win2k)環境でのint値のソート時間.(単位:μ秒)
Athron64X2 5200+(2.6GHz) 8GB(Vista64)環境でのint値のソート時間.(単位:μ秒)
上から3つが O(n^^2^^)、次の2つがO(nlogn)。 10,20個程度だと、大差ない雰囲気があるけれど、 1000個とか10000個のソートになってくると O(n^^2^^)ものとO(nlogn)モノとで1~3桁 時間が違ってきてる。 (当然それ以上だとさらに差は拡大するわけで) 数が少ないときは比較的似通っているといっても、 挿入ソートは目だって速く、 上記結果だと、TM5400では int 50個程度までなら、Athron64X2では int 100個程度 までなら、コムソートやクィックソートより速い結果になっている. (もちろんCPU等環境の違いで個数は大きく変わる)
で、クイックソートは、一定個数以下になったら挿入ソートに切り替えることが
可能で、それによって速度を上げることができる. std::sort()も実はだいたい同様でクィック+挿入(少なくともvcのはだったはず.)。 若干遅い結果なのは汎用性等の書き方で多少オーバーヘッドがあるのか. この差が問題になるかどうかは、用途しだいだけど、 普段気にするようなレベルではないだろう. ※追記>std::sort()の実装は(普通?は) 再帰が深くなるとヒープソートに切替えるらしい. (イントロソートらしい?)
ただ、Cライブラリの qsortもアルゴリズム自体は同様と思われるが、 こちらはCプログラムでの汎用性のため (とくにintなんていう単純なデータのソートとしては) オーバーヘッドが大きくなってしまっている模様。 quick+挿入に対して、1桁違うことはないだろうが、 下手すると数倍の時間がかかったりして、結構大きい。 C言語の場合は、性能のためにあえてqsortを使わず、 自前で(コムやクィック)ソート・ルーチン用意するのは、 ありの選択. (が、性能と手間を思うと、C++環境にできるなら とっととC++に移行してしまうのが吉かも) ※クィックソートから挿入ソートへの切替個数は、 コンパイラ付属のものにあわせて 32個にしている。 アルゴリズムの本(20年位前にかかれたもの)をみると、 CPU性能やコンパイラ性能等でかわってくるが だいたい 10~20 位、って値が示されているのだが、 最近のCPUの性能がいいのかより大きい値のほうが速いようだった.
ついでに他のソート時間を測定してみる.ついでに、wikipediaのコムソートの説明にあったcomb sort 11 と、 数日前に流行?っていたやねうらお氏の挿入ソートも試してみた。 (ちょっとはしょりすぎて100~1000の精度がいまいち...) Crusoe TM5400(600MHz) 256M(Win2k)環境でのint値のソート時間.(単位:μ秒)
Athron64X2 5200+(2.6GHz) 8GB(Vista64)環境でのint値のソート時間.(単位:μ秒)
Athron64X2 5200+(2.6GHz) 8GB(Vista64)環境でのdouble値のソート時間.(単位:μ秒)
comb sort11については、個数が多いときには効果あるようだけど、逆に個数が 少ないときは増えた if 文のペナルティが出るのか、遅くなってしまっている。 その効果もささいな感じなので、無理に使う必要はなさそう. やねうらお氏の挿入ソートだけど、説明読んだときは効きそうに思ったのだけど、 結果は、よくなったり悪くなったり、で、ちょっと残念な結果でした。 いや、なんか、自分がポカやってる可能性は多いにあるのですが。 (TM5400の50個の列の値は、当たり所悪く他の処理時間が混ざったパターンぽく) やなう版は、最内側のループの外側とはいえ、外のループの内側に if文が増えているので、そのへんが影響して、 コンパイラの最適化やCPUのキャッシュ具合、分岐予測 等、 何かバランス的にくづれて、メモリー代入のペナルティと同等か それ以上のペナルティになってしまっているのかな? 追記:こっちを書くまで気づいてなかったけど、 比較回数が1回増えてるので、コピーしないですました時間より 比較時間が増えるのが無視できないということかも. (元記事の前提と違う状態で使ってしまったとも)
その他
しらべていないけれど、 (己がかいた)クィック+挿入は、一見性能よさそうにみえるけど、 個数がある数(以上?)だと、急激に時間がふえてしまったりしていた. ちょっと困った. あとソースをコンパイルしたexeや使ったバッチ等
2009-12-15[火] ソートについて2
test1 補足
やねう版の結果がちょっと気になったので、手元ですぐ動くvc以外の
コンパイラでも試してみた。
プログラムのほうも時間計測の関数変えたり結果出力編集するの面倒だったので若干修正.
実行環境は athron64x2 5200+ 8GB(Vista64)環境.
(だいたい似たようなもんだけれど、それなりに誤差があるので雰囲気見るために)
さらに quick sort の一部として使った場合の結果は、微妙.
でもまあ、基本どんぐりの背比べ、だけどよくなるコンパイラもある、んだから、汎用的に書く場合は やねう版 でいいかも、と。 (下手な書き方してでっかい要素をそのままソートする場合にはやねう版のほうが有利な気もするし)
※ と結論にしたけれど、後のtest2~は test1補足を試す前に調査してたのでやねう版になってません
ついでに std::sort。 gccやwatcomだと他の結果がいまいちのことがあっても 付属stlのstd::sortは速いので、 基本的には付属のを使うのが吉のよう. vcのは若干、bccのは結構、遅いけれど... bccについては使ったのは数年前のもので最新じゃないし、 borlandのc++はその時々に付属するstl(の元)が変わったりするので… てみたらdinkumwareだった(VCと同じ元ネタ)...orz ※追記: std::sortの実装は単純なquick+挿入なだけじゃなくスタック溢れ対策?もあるよう.
※追記: vcのコンパイルオプションが不味く、スタック等のチェックルーチンが結構生成されていた. (関数分割や分岐が多いと不利だった模様). チェックを生成しない設定でコンパイルしたら、 結論がかわるほどの大きな違いはなかったけれど、 std::sort等ややねう版の結果も心持よくなったような気も.
test2 引数の数の違いの影響関数呼び出しオーバーヘッドが性能に影響する、状況だろうから、 じゃあ、2引数版(<専用) と 3引数版(比較ファンクタ指定) でどれくらいの差がでるか、と思い、試した.(引数の数というより、ループの最内側で使われる引数で渡された'比較'が、ちゃんインライン展開されているや否や) cでなくc++のテンプレートで実装. std::sortに引数をあわせている. また quick sort とかいているけど実際には挿入ソートを使ったバージョン. (以後単にquick sortと書いていても同様) vcでの結果(単位:μ秒)
他のコンパイラもだいたい同様の傾向.
引数が2個か3個かの違いは、(ちゃんとオプティマイズされてたら)気になるような
差は見受けられず.
てことで、実体つくるなら3引数版をつくってそれを呼び出す2引数版を作る、で よいのだろう.
test3 std::listのソート(追記: マージソート失念して間抜けなことしてます..orz)
std::list のソートのテスト. 比較のため、
してみた。
SmpClass版(mallocポインタやstd::vectorを持つ適当なクラス) (単位:μ秒)
std::string版
int版
基本的には SmpClass版の結果が、実使用に近いものだと思う.
で、みてのとおり、std::list でソートしたくなったら、
std::list のメンバーの sort() を使う
という当たり前の結論. intやdoubleのような小さい要素で少量のときは逆転してるけど、 そもそも個数がn個程度と限定されているならばlistでなくvectorあたりでよく. 無理に bidirectional iterator を受け取れる quick sort 作ってまで やることじゃない、と. あと、そのものstd::list自体のソートが必要なく、 途中の処理として整列された順番でデータ舐めたいだけならば、 4つ目のように、 要素へのポインタを集めてそれをソートして使うのが吉かも.
test4 大きめのオブジェクトのソート、スマートポインタのソート
普通は、大きめのオブジェクトの実体を直接ソートしない。しないですむように作る。
もっとも、大きめのオブジェクトはポインタなりハンドルなりで扱い そのまま管理/やりとりすることはないだろうで、 c++だとスマートポインタの類による管理も増えている.
じゃあスマートポインタのソートはどう?ってことで、試した.
以下 SmpClass (mallocポインタ,std::vectorメンバー有り)の結果(単位μ秒) vc2008版(64バイト)
mingw32-gcc(4.4.0)版(56バイト)
上から順に.
shared_ptrはいろいろ便利だけれど、やっぱりその分実行時コストがかかってしまう。 それが気にならない箇所ならいいけれど、 ソートのような場合は考えたほうがよさそう. intrusive_ptrは、ポイント先になるクラス側に参照カウンタ処理が必要となり、 shared_ptrより使い勝手は落ちるけれど、 参照カウンタの処理自体は shared_ptr よりも素直な状態なので、 実行時コストは小さい. で intrusive_ptr のほうは、ソート済の生ポインタをも一度intrusive_ptrに することができる(もちろん、このへん、操作をあやまると参照カウンタ管理を 破綻しかねないので注意深く...)が、 shared_ptrは生ポインタ化してソートした結果を元のshared_ptrに戻す方法が なさそう. (shared_ptrの指す先でなくshared_ptr自体のアドレスでソートすればだが不本意)
追記:比較条件が単純でソートキーが値一つですむようならば、 ポインタのみの配列でなくソートキーとポインタのペアの配列を ソートしたほうが速くなりやすいと思われる(test5)
ソース&実行ファイルとりあえず、今回のソース等を固めたもの.
2009-12-17[木] CPU換装→AMDLLD64青画面どうもPC組立やパーツ差替のたびにトラブルってるような... ソフマップの特価につられつい CPUを PhenomII945に換装したら、 vista起動ログイン直後に必ずブルースクリーンになってしまうのでした. (前回は9月頃MBのBIOS更新に失敗してMB交換. でもそもそも BIOS更新した理由はMBで不具合のでるGカードを買ったせい) いやsafeモードだと問題なく.メモリテストも問題なく. BIOSはちょっと古かったので更新かけたけど変わりなく. 青画面のメッセージには amdlld64.sys(AMD Low Level Device Driver) の中のアドレスが表示されていて、こいつが犯人ぽい. ググッたところ日本のサイトでは見つからなかったけれど、海外にちらほら. 初っ端に見つかる こち ら が正解のよう.
MBの種類は違うけれど、症状は同じ.
対処は、
AMDLLD64.SYSがなくていいのかは
わからないけれど、起動できないよりは、で
(?別のドライバに置き換わってるのかも?).
2009-12-18[金] 夢にみたソフトxp64で64ビットwinに移行して以来、自宅メインPCでは 16ビットdos用の exeが使えなくなっていて、 それもあって win7bisのxp付はちょっと魅力的だったりしたのですが. (いやイザとなればサブPCはw2kだし、virtualpcでwin9xという手もあるけれど)
最近ごそごそ別件で検索してたら なるMSDOSコンソールなエミュレータが2つも開発されていた模様. 双方公開されて日が浅く... というかwin7(64)で16bit exe使えず 不便だからと作られたもののよう. ハードのエミュレートじゃなく、dos(+α)部分のみで 入出力が仮想ドライブじゃなくて通常のドライブ(環境)のままで、 まさに、かって欲しかった(作れなかった)ソフトそのもの. MSDOS Playerのほうは msdos.exe hoge.exe files のように単発実行できるもの. lccコンパイラ使うためってことらしく他の32ビットツールとの連携もやすそう. VTDOSのほうはv-text環境込みのdos窓(shellコンソール)みたいなもののよう. v-text(dos/v)版のvzやfdも使えるらしい. こちらも16ビットexeだけでなく32ビットexeも呼び出せる模様. (それもあってか設定がちょっと面倒そう...己は上手くいってませんorz)
で、まあ、双方のサンプルに mg.exeって記述があって思わず笑ってしまったのでした。 (今でも触って下さってる方がいるなんてありがとうございますです)
ただ、喜んだのはいいのですが、すっかり16ビットdosツールとは 疎遠になってしまっていて、これを機に16ビットツール環境復活...したいけど,どこにバックアップしまったやら. (試すためにこのサイトの16bit-dosツールからmg.exe落としたりとちょっと間抜け)
で、折角だからfreedosからとってきたcommand.comと、こちらのos9/6809 L1 エミュレータ(v1.1)とを組み合わせて
C:\Users\myname\OS9>msdos command.com /c echo hello | os9l1 place \* world hello world world
て具合に msdos(8086) と OS-9/6809 の夢の競演をさせてみました.
2009-12-20[日] 古PC復活メモ(遅延書込) 最近、古い5インチFDDや3.5インチMOをサルベージしたく バラしたままだった古PCを1台復活させたが、 この手のことはやってるときは楽しく、 つい他の古PCの復活もやってしまったのだった.
pen3 800MHz前後まずは、NetVista6842(pen3 866MHz i810E mem512MB hdd:120GB) とか NetVista6881(celeron 700MHz i810 256MB 80GB)とか Mate MA07H(pen3 800MHz 810 256MB 80GB)とか (昔中古で安いからと買いすぎた代物). NetVistaは家用サーバーで使っていたのを引退させたものだから、 いまさらそんなモノにするのもつまらなく、 デスクトップな linux ディストリビューションを 試すことにした. あと、PCI付のNetVistaにはPCIのRivaTNT(やG400)が残っていたので、 それをつけてみた. 結論から言えば、このスペック程度でデスクトップ利用するのに 一番いいOSは、やっぱり Win2K、だろうというのが実感.
最新のwin7(rcだけど)をNetVista6842 に入れたら、
linux等フリーosも、グラフィックアクセラレータ対応ドライバーの有無がネックだろうか.
nVidiaの古いチップは、オープン(あるいは解析済)というわけでは ない模様. メーカー製ドライバは古いxに対応のものは存在しているが、 最近のXorgには未対応のよう. このために古いディストリ入れるのも楽しくないので、 また810は多少はアクセラレーション効くのかAGPx2なのがPCIよりも有利に 働くのかマシな状況だったため、結局TNT(PCI) はお払い箱にした. ちなみに ATIのだと、数年前に情報オープンになってて最近 よくなってきているらしく、 Radeon9600gtをつけた別のマシンで試しに ubuntu(gnome) いれたときは、アクセラレーション有効になるとまずまずの感じだった (それでも検索するとメーカー製ドライバのほうがよいような記述も みかけたが、インストールの面倒を思うとフリー版でよいかと) と思っていたら こちらの記事からすると、 Kernel 2.6.33 あたりでnVidiaの古いチップ対応がマージされるらしい? ということはもう数ヶ月まてばマシになるのかもしれない. というか、Fedoraだと今、対応済みってことなのだろうか? 気力ができたら試そう (debian系に慣れたため、他を弄る気が薄く...) ただ、グラフィックドライバーの問題を抜きにしても ubuntuは pen3 866MHz 512MB程度のスペックで使うには重かった. (不要なプロセスも多少殺したが、いまいち) メモリ256MBのほうに, debian+lxde や u-lite(ubuntu+lxde) を 入れたときは結構よく思えたので、 じゃあとgnome版を試したのだが、レベルが違った. あきらめたほうがよさそうだ. 日本語対応を思うと ubuntuは魅力的なんだが... u-liteになると結局日本語関係いまいちな感じになるので、ううむ. その他 ReactOSは、うまくインストールできず. 他にもLiveCDモノもいくつか..でpuppyは結構よい感じだった(後述). 日本語整備されたものをみちゃうと、堕落してしまう ただ結局のところ、512MBのPCはdebian入れてサーバー的にLAN接続、 他はpuppyとか入れっぱなしで放置という結果になった (放置分だれか引き取ってくれないかしらん)
puppy linux軽いといううわさの Puppy Linux も HDDにFULLモードで入れてみたが、たしかに軽いようだ. 先のlxdeな環境に比べても、頭一つ抜き出ている印象をうける. jwmというのも軽いのだろうが、全体で上手く調整されているのだろうな. (窓移動で中身表示せず枠だけってのは遅いマシンでは嬉しい. みっともない窓描画みせられるよりか、ずいぶん印象がよくなる)
なにより日本語対応が思いのほか行われていたのがうれしい.
ただ個人的には標準のファイラが好みでなかったのが痛かった. パッケージシステムも、 基本的に1CD起動、RAMディスク運営のシステムとして 調整されているものだから、 そもそもdebianやubuntuと比べるのはお門違いなのだが、 なまじまとまったシステムのせいか(まあ面倒だし)、 ソース落としてきてまでインストールという気にもなれず. RAMディスクベース用にロードモジュールを用意するのは、 os-9のロードモジュールを連想してある意味楽しいそうなんだが.
x,gtk+?ubuntu(9.10)の外観の設定、では視覚効果の指定で3つの状態が選べるが、 radeon9600gtを入れたPCで試していると、 効果無しを選ぶとアクセラレーションが効いていないようにみえる. 逆に通常効果(追加効果)を指定したほうがきびきび動いてるようだ (810だと通常効果を選べなかった). あとdebianで、ためしにmac4linを入れたのだが(窓まわりはそれらしくなったけどドック関係は失敗)、非常に激重になった. 使い物にならないのでアンインストールしたが、元どおりにならず、マシになったとはいえ描画が非常に重い状態. よくみると、窓に半透明影が残っている...非力でないPCでubuntu動かした ときはmac4linいれるまでもなく影付きなので、元々の機能でon/offできるのか? こちらをみてて
> gconftool-2 --type boolean --set /apps/metacity/general/compositing_manager FALSE でoffできた. offできると今度はインストール前よりも速いような?気も. (アクセラレーションがきいた? わからない) xとかgtk+,gnomeの設定がちゃんとしてあげられたら 非力なマシンでももっとよくなるのかな? このへんのところ調べたほうがよいのだろうが...疲れた.
DynaBook GT475
msdos playerとかに触発されたこともあって、
調子乗って、十数年前の win95 なnote機 DynaBook GT475(486 75MHz 24MB)
も弄ってしまった.
linux等でコンソールのみだとしても、よほど古いディストリ等でないかぎり 辛いサイズに思う(一度入れたが日本語使えないのはやっぱり嫌で)
もちろん dos/v 入れる分にはそこそこ十分だ.
HDDは元の500MBのものから、余ってた30GBのモノに付け替えた. マシンのばらし方はこちらのサイトがまだあったのでありがたく. E-IDE と表示されてるので 8G までいけるとおもいきや BIOS的には 500MBまでなのか、GT475につなげて fdisk等すると 誤った容量が表示されそのまま作業すると不味い状態.
まあBIOS で大容量HDDをちゃんと認識できなくても、
起動したosがサポートしていれば通常で利用できることが多いので、
あらかじめ 別PC で freedosにて fdisk&format
(念のため起動ドライブは8GB以内の4GBに設定)
してから GT475につなげたところ 4GB,24GB にアクセスはできて一安心.
折角だからとパーティションきってlinux等もいれようとしてみたけれど、 biosが想定外なのか grubやliloを使っても2つ目以降のパーティションからの起動が 無理のよう. ブートできないシリンダだとおこられる. 2つ目のパーティションが500MB以内にくるように 1つ目のパーティションを100MBにした状態でも駄目. なので複数インストールはあきらめて一つだけにした.
で、結局いれたのは、Win98...orz FreeDOS関係でなんとかしたい、と思ったが、 lfnのサポート具合のこともあるし、 ネット関係を思うと、 LANカードのドライバー等はなんとかなるにしても、 LAN内の他のPCとのやり取りの利便を考えれば 結局win機がベターなのだった. (ただwin95無印はfat32無しだしその他ドライバーが見つからず... win98で自動認識されてインストールというのが吉だった) また、せめてtelenet端末として、と思う場合も、 utf8が使えるdos/v用の端末ソフトがあるや否や、 で、移植や改造が頭によぎりバカらしくなり.
とりあえずwin98ならば teraterm 動作ということでok.
*まあ、使えないマシンを復活させるのは楽しくここ2週間ほどちまちま弄ってたけど、 ふと我に代えると非常にむなしいもので…… 次またやってしまう率を減らすためにメモといったところ. 思い返すと古PCは osお試しインストールすることこそが 目的なのかもしれないと思えてくるが... 最近は、 メモリもCPU速度もありisoイメージ直インストールできる メインマシン上の VirtualBox での作業するほうが吉だものな.
2009-12-24[木] mg.exe LFN対応
今更ながら mg.exe を LFN対応してみた.(これ) が、msdos player はLFN未対応だったらしく..orz
vtdosのほうは、動いてくれた.
command.com は、PC DOS J7.0/V のCD発掘できたので、それを利用.
しかし、ドキュメントを読む分には素でも動きそうなのだが. ドキュメントやCOMSPECを見ると vtdcmd.exe というものを実行していそうだが、 配布物の中にそのexeファイルはなく. 仮想名かもと思うが、動かないとこみると、やっぱり必要なのかも? ...が、とりあえず command.com 入れて動いたのでよしとしておこう.
(追記)
といっても、ax=71a7h; int 21h (win32なファイル時間をdosファイル時間に変換するLFN用システムコール)を実行してみて、エラーがax=0x7100になるかどうかを
見てるだけ.
あっと、lfnのシステムコールは こちらを参考にしてます.
|