2/27 (月)
[Prog] Linux のシグナル処理の速度
訳あって Linux のシグナルの処理速度の測定に入る。 こんな感じのプログラムでヘコヘコ速度測定。
/* * segvtest.c */ #include <setjmp.h> #include <signal.h> #include <stdio.h> static sigjmp_buf return_point; static volatile int counter0 = 0; static volatile int counter1 = 0; static void signal_handler(int sig, siginfo_t* sig_info, void* sig_data) { counter1++; siglongjmp(return_point, 1); } int main(int argc, char **argv) { char* p = 0; int i; /* シグナルハンドラの設定 */ struct sigaction newAct, oldAct; sigemptyset(&(newAct.sa_mask)); sigaddset(&(newAct.sa_mask), SIGSEGV); newAct.sa_sigaction = signal_handler; newAct.sa_flags = SA_SIGINFO|SA_RESTART|SA_ONSTACK; if (sigaction(SIGSEGV, &newAct, &oldAct)) { perror("sigaction error"), exit(1); } /* わざとスタックオーバーフローを発生させてハンドルする */ for (i = 0; i<1000 * 1000 * 10 ; i++) { if (sigsetjmp(return_point, 1) == 0) { counter0++; *p = 0; /* null pointer exception */ } } printf("counter0=%d counter1=%d\n", counter0, counter1); return 0; }
10 * 1000 * 1000 回 メモリフォールトを起こして sigsetjmp → SEGV シグナル → siglongjmp を繰り返す。 経過秒数を 10 で割ると 1試技のμ秒数。
予想通り IA-64 は結構シグナル処理が高速。
ただ GCC の問題なのかメモリオーダリングなの問題なのか、
GCC 3.2.? の -O2 までは正常に動くのだが、
-O3 からは最後の出力が counter0=0 counter1=5000000
になる。
Xeon MP (2.0GHz) | Itanium2 (1.3GHz) | |
---|---|---|
Pthreadなし | 6.0μ秒 | 1.9μ秒 |
Pthreadアタッチ | 6.0μ秒 | 2.3μ秒 |
もう少しプログラムに工夫がいるかしら。
追記:3/1
IA-64 でコンパイラの最適化レベルを上げた時に、 10,000,000 回実行したつもりが counter0 が 0、 counter1 が半分の 5,000,000 回としか表示されないのは、 やはりメモリオーダリングが原因だった。
POINT1 の位置にメモリバリアを置くと、
counter1 の書き込みは順序化されるので
シグナルの発生した本当の回数が分かるようになる。
この時の printf の出力は counter0=0 counter1=5000000
となる。
やはり半分しか SEGV シグナルは発生していない。
解釈としては、
ループ誘導変数 i が書き込まれるタイミングの
2回に1回は null pointer exception が追い越していくようだ。
counter0 に至っては1度もメモリに実際の書き込みが発生していないので、
null pointer exception に必ず追い越されるということになる。
期待したようにプログラムを動かすには、 POINT2 の位置にメモリバリアを立てるのが正解のようだ。 counter0 も counter1 も 10,000,000 回となった。
#define membar() asm volatile("mf":::"memory") static void signal_handler(int sig, siginfo_t* sig_info, void* sig_data) { counter1++; /* POINT1: membar(); */ siglongjmp(return_point, 1); } for (i = 0; i<1000 * 1000 * 10 ; i++) { if (sigsetjmp(return_point, 1) == 0) { counter0++; /* POINT2 membar(); */ *p = 0; } }
VMware ESX Server のメモリ管理
Memory Resource Management in VMware ESX Server という論文を見つけて読み読み。 USENIX の OSDI'02 の論文みたいね。 ESX Server は下の 1. の Disco という方式を基にしているようだ。 ESX Server 側で page fault を拾って、 machine address space (本当の物理ページ) を physical address space (ゲストOSから見たときの物理ページ) として 割り当てているようだね。 ゲストOS側のマシンの TLB はどうなっているのか不明。
- Edouard Bugnion らの Disco: Running Commodity Operating Systems on Scalable Multiprocessors
- A Survey on Virtualization Techniques
- Virtual Memory in the IA-64 Linux Kernel
ついでに以下の本を購入。
一夜漬けの知識でどこまで通じるか?
- 詳細Linuxカーネル 第2版 (Daniel P. Bovet、Marco Cestati 著、高橋 浩和ら訳、オライリー・ジャパン)
- 説明は不要?
覚え書き
家賃を払ったよ。
2/24 (金)
[Prog] 2進化10進数 (BCD) の計算アルゴリズム
わけあって BCD 計算のアルゴリズムを勉強中。 参考ページ
1. のリンクによると、 足し算・補数のアルゴリズムは以下のようにかけるようだ。 なかなか美しい。
u32 add_bcd(u32 a, u32 b) { t1 = a + 0x06666666; t2 = t1 + b; t3 = t1 ^ b; t4 = t2 ^ t3; t5 = ~t4 & 0x11111110; t6 = (t5 >> 2) | (t5 >> 3); return t2 - t6; }
u32 tencomp_bcd(u32 a) { t1 = 0xFFFFFFFF - a; t2 = - a; t3 = t1 ^ 0x00000001; t4 = t2 ^ t3; t5 = ~t4 & 0x11111110; t6 = (t5 >> 2) | (t5 >> 3); return t2 - t6; }
私は IA-64 には64ビットレジスタを8ビット×8個のパック形式とみなす並列計算 padd/psub があるが、 これで BCD 計算ができないか思案中。 Both the DEC (later Compaq) Alpha and the Intel MMX extensions to the 80x86 family provide for this, allowing 64 bit words to be divided into many subfields, with carry propagation from field to field interrupted, and with the carries captured in a form allowing their manipulation. とあるし MMX でできるなら、IA-64 のマルチメディア命令でもできそうな気がする。 要熟考。
追記:3/5
add_bcd 分は思いついた。
u32 add_bcd(u32 a, u32 b) { t1 = a + 0x66666666; t2 = t1 + b; t3 = padd(t1 + t2 + 0x55555555); /* バイト単位符号付飽和 */ t4 = pcmp(t3, 0xffffffff); /* バイト単位一致比較 */ t6 = t4 & 0x66666666; return t2 - t6; }
元の add_bcd は a + b + 0x06666666 (=t2)
で
キャリー伝播付きの加算を行い、
この後で桁溢れを起こさなかったバイトからは 6 を引き、
桁溢れを起こしたバイトからは 0 を引く(つまり引かない)。
後半の役目を果たすのが t6 だ。
t6 の合成にマルチメディア演算が使えそうだが、
もうちょい速くならないものかしら?
追記:4/18
よく考えると padd はバイト単位符号付飽和演算で、 必要なのは 4 ビット単位飽和演算だから駄目じゃん。
2/23 (木)
深遠なる Garbage Collection の謎
自称 Garbage Collection 研究家なのですが、 Garbage Collection を何て訳せばいいのか知りません。 教えて Google!!
検索語 | 検索結果 |
---|---|
"ガベージ コレクション" | 約 58,500 件 |
"ガーベージ コレクション" | 約 29,100 件 |
"ガーベッジ コレクション" | 約 16,200 件 |
"ガーベジ コレクション" | 約 238 件 |
"ガベジ コレクション" | 約 81 件 |
"ガッベージ コレクション" | 約 14 件 |
"ガッベッジ コレクション" | さすがに0件 |
正直「ガッベージ」はないよな。
直訳の「ゴミ集め」が割と市民権と的を得ていると思います。
2/22 (水)
知らない間に WinCDR の開発・販売元が Aplix から Ulead に
昨年の5月3日に購入したPLEXTOR PX-716AのDVD-Rドライブだが、 手持ちの WinCDR 7.0 がドライブに対応していなくて、DVD-ROM ドライブとしてしか使っていなかった。 先月のことでさすがにバックアップの重要性が身に浸みたので、金を惜しまずに WinCDR を買い直すことにした。
Aplix のホームページに行ってみるとないじゃん。 そう言えば DoCoMo が Aplix の JBlend を採用する時に、DoCoMo から「うちと商売するなら CD-R ライティングソフトなんてグレーな感じのソフトを売ってちゃダメよ」と言われて事業を売却した、という噂を聞いたことがあったなぁ(風聞の流布)。
Google で検索するとなんと Ulead に移っている。 まあいいや。 Ulead から WinCDR 9 アップグレードダウンロード版(5,145円)を購入。 途中、メンバ登録、商品購入の確認、クレジット購入の確認と3回もメールが行き来きしてようやくダウンロード可能。
RedHat Enterprise Linux の CD イメージが 20GB ぐらいあるのをバックアップ。 続けさまに 5 枚灼き焼き。 やっぱり x8 倍速はいい。
2/20 (月)
Para-virtualization についての雑考
仮想マシン(VM) の上でターゲットマシンををエミュレーションする時、ターゲットマシンの仮想 CPU はキャッシュは無視せざるえない。 キャッシュは透過的にはたらくのだから、キャッシュ制御命令を実行するふりだけしてキャッシュは無視すればいい。
一方で TLB で本来仮想 CPU には不要、むしろない方がいいのだが、TLB がないとするとプログラムの動作が変わってくるのでエミュレーションせざるえない。
問題はホストマシンの TLB ミスとゲスト仮想 CPU の TLB ミスは全然別物だから、どうやって仮想 CPU の TLB フォルトを上げるかだなぁ。
ファイル復活はまだまだ続く
先月に誤って消去してしまった HDD の復旧作業を続けているが(1/9、1/10、1/11)、最後の一個の HDD がうまくいかない。
CENTURY NewニコイチBOX (CTC35U2BL) に接続した 160GB HDD の Maxtor DiamondMax Plus9 (6Y160P0) に完全復元PRO2006でクラスタスキャンをかけているのだが、処理中にセクタ解析速度が低下していっている。 10時間で 320,159,384 個ある物理セクタのうち約300,000,000 セクタまで終わるが、その後の進捗をみると今月中には解析が終わらない勢いだ。 タスクマネージャで見ると CPU 使用率が100%近くになり、recovery.exe の仮想メモリサイズが単調に増加するのだ。
販売元にサポートのメールを出してみた。 回答待ち。
追記:2/27
回答が返ってきた。
お問合せの件ですが、一度に160GB分のスキャンを行うのではなく、
範囲を区切って何度かに分けてスキャンを行ってください。
…
2/18 (土)
[Prog] スレッドのスタック領域のアドレスとサイズを取得するには
UNIX 系 OS でスレッドスタックの座標をどうやって取得するのか調査中。
OS | API | インクルードファイル |
---|---|---|
Linux | pthread_getattr_np | pthread.h |
FreeBSD | pthread_attr_get_np | pthread_np.h |
OpenBSD | pthread_stackseg_np(3) | pthread_np.h & sys/signal.h |
MacOS X | pthread_get_stacksize_np pthread_get_stackaddr_np | pthread.h |
Solaris | thr_stksegment(3thr) | thread.h & sys/signal.h |
後は NetBSD、HP-UX、AIX、Tru64 UNIX、IRIX かしら。
2/17 (金)
[MyWeb] 「スタックオーバーフローのハンドリング (Stack Overflow Handling)」のページを修正
結構、間違いが多かった。
更新
2/15 (水)
2/14 (火)
2/12 (日)
久しぶりに秋葉原に出る
まずはモスバーガーでハバネロフォカッチャを食べて腹ごしらい。
これから仕事に必要になる数値演算アルゴリズムの本を物色したが見つからず。 ニ進化十進数の演算方法とかが載っている本が欲しかったのだが。
しょうがないのでDVD を買って帰る。
今日見つけた理不尽を感じる画像
歩道側が外れているのはなぜ? 何がぶつかったんだ。
いいのか。 共食いだぞ。
2/11 (土)
[Java][Prog] VTune で苦労する
VTune Performance Analyzer 3.0 Update 1 for Linux を使って Java プログラムのパフォーマンスモニタリングをやろうとヘコヘコ手作業。
A. Linux 2.6 系カーネルの NPTL 対策
Linux のスレッドは 2.6 からカーネルランドの NPTL スレッドに切り替わったが、VTune や類似の計測ツールでは計測期間の途中で作成されたスレッドのデータが取れないという問題がある。 計測開始時点でプロセスのスレッドを認識してデータの収集を行うのだが、途中で生成されたスレッドをうまくハンドリングできないらしい。
B. Java 用の Pause/Resume API がない
VTune がプログラムの計測に行う期間は「起動 n 秒後から m 秒間の計測」という「GUI によってボタン操作」の他に、「プログラムの中で専用 API を呼び出して計測期間を指定する」というのがある。 A. のような事情によって後者の手段を使わざるえない。
ところがマニュアルには Java 用の com.Intel.VTune.VTuneAPI クラスを使えという指示があるのだが、VTuneAPI.class がみつからない。 おかしいなぁ。
やっていることは予想がつくので JNI で専用 API を呼ぶ VTuneAPI を自前で作ってしのぐ。
C. バッファイサイズが大きすぎると駄目みたい
VTune のオプションの指定はかなり厳しい。
-sb
オプションはサンプリングに使うバッファの大きさを指定できる。
バッファサイズ分のイベントデータが採取できるとファイルに書き出されるので、大きいほど負荷が小さいようだ。
デフォルトは 2000K バイトなのだが、欲を出して 1GB ぐらいを指定して計測をする。
すると以下のようなメッセージが出る。
The Sampling Collector failed to collect data because the selected event(s) did not occur.
最初は自作の B. の API がまともに動いていないのかと思ったが、どうやらそうではない。 バッファが大きすぎると最初のファイルの書き出しが行われる前に計測が終わるようで、バッファのフラッシュなしでプログラムが終わってデータが残らないようだ? ム〜。
2/9 (木)
松下電器より心からのお願いです
松下電器が全国の全世帯に配った欠陥石油温風機の回収のお願いのはがきが到着。
オライリーの本
ちょっとだけど記事を書くことになった。 締め切りは月末。
2/8 (水)
ドナドナドナ
来期(4月)より武蔵中原から新横浜へ勤務地が変更になる。 元住吉に住んでいるので電車(新横浜までは東横線の菊名駅→横浜線で新横浜)で通えなくはないのだが、せっかく独り身なんだから会社まで歩いて通えるところに引っ越したいところ。 もう少し早く分かっていればブツブツブツ(1月19日の日記)。
業務内容も今の J の仕事から変わることになる。 2年ぐらいの時限を切って **** の開発をすることになるのだが、どうなることやら。 もう一つ *** の IA-64 ポーティングをするチームもできる。大丈夫かしら?
ラーメン博物館に毎日通えるようになることが慰めかぁ。
UC CARDの Web 明細サービスキャッシュバックの終了
UC カードは紙の明細書が不要を選択した人に最大年1,000円のキャッシュバックがあったが、 クレディセゾンとの統合の影響か Web 明細サービスを選択する人が飽和したのか 中止になるようだ。
UC カードの Web 明細は、 そのページまで行ってボタンを押せば明細が見れる or Microsoft Money で取り込めるデータをダウンロードできるというもので、 Money を持っていないわたしにゃ使い辛いサービス。 せめて XML 形式のデータがあれば解析して使えるのだが。 というか明細書を直接 e-メールで送ってもいいんじゃない。
単純に横浜に近くなるというのは慰めになりませんか?
と横浜市民は思ってしまうのでした。
おしゃれな街 横浜市民になってカレーと中華三昧は悪くないですね。でも、引っ越すのは面倒です。誰か代わりに引っ越してくれないかなぁ。
あとは、後から思いついたのですが、元指導教官のお宅や職場へいつでもうかがえるという特典もあります。滅多に発動されないかもしれませんが。。。
2/7 (火)
寒い…
朝起きるとえらく寒いと思ったら、 みぞれ混じりの雪が降ってうすく積もっている。
布団を捨ててしまい今は厚手の毛布を2枚重ねて寝ているのだが風邪を引きそう。 来年は布団を買おう。
TODO
- SACSIS の論文査読がまわってきて思い出したのだが、 情報処理学会の会費払ってねェ。
- ACM の会費も払ってねェ。
- 大学の同窓会の会費も払ってねェ。
2/6 (月)
iTMS で購入した楽曲の DRM なし版をダウンロード
iTMS の楽曲はユーザー毎に異なる ID で暗号化されている。 だから異なる人がダウンロードした mp4 ファイルはビット列が一致しない。 この暗号化は Apple のサーバー側で実行されていると思っていたのが、 どうもそうではないらしい。
iTMS サーバーから送られていくる楽曲データは暗号化されておらず、 それをクライアントの iTunes 側で暗号化しているようだ。 Hymn Project では、 一度購入した楽曲は再ダウンロードが認められているのを利用して、 iTunes のフリをするダミークライアントですでに購入した楽曲を再ダウンロードし、 DRM なし版の mp4 ファイルをゲットできる。
ツールとしては JHymn が便利そう。
[Prog][Unix][Windows] 穴空きファイル
UNIX には 疎なファイル(sparse file) とか holeのあるファイル とか 穴空きファイル とか呼ばれているものがあるが、 Windows でも Windows2000 以降(の NT系 OS で NTFS を使っている場合に)は sparse file は作れるという覚え書き。
Sparse file がどういう由来で導入されているのかは良く知らないが、 UNIX だとコアファイルでよく使われる。 コアファイルはメモリイメージダンプなわけだが、 メモリ空間の中で実メモリがある場所は飛び飛びなので、 ナイーブにダンプしてしまうと実際に使ったメモリよりもはるかにでかいファイルが生成されてしまう。 ダンプイメージを sparse file で持つと、 実メモリのない部分はディスクに書き出さずに済むので節約になる。
Windows でも WinDbg は使っているっぽいが、 それ以外だとこの機能はどう使うんだろう。
P.S.
私が使い方を考えると、 wget でディレクトリをごっそり持っていくダウンロードを妨害するために、 ディレクトリインデックスに sparse な巨大ファイルを作っておくとか…
ちょうど今月の DB Magazine (3月号) に、Microsoft SQL Server が、
データベース snapshot 機能の実現のために sparse file を使っている
という話が載ってました。(50頁)
連続した「0」部分の多い巨大データ全般に使ったり、あるファイルのオンラインバックアップ(スナップショット)取得中の書き込み履歴用とかに使えます。
DB 系のスナップショットというのがありましたね。Windows2000の場合はそれが本来の使い方かもしれません。
> Yas さん
はじめまして。
オンラインバックアップの書き込み履歴というのは面白そうですね。これはオリジナルファイルと同じサイズの sparse file を memory mapped file 経由で書き込むという方法でしょうか?
2/5 (日)
[Bench] SPEC CPU2000 スコア
なんとなく続く SPEC CPU2000 スコアの観察。
注目は Intel Core Duo T2600 のスコアが登録されたこと。 しかもこれ登録したのは Lenovo で、計測マシンは ThinkPad T60。 ノートパソコンの SPEC CPU2000 登録は初ではないだろうか? CINT2000 は int2000 が 1,754、int_base2000 が 1,748。 CFP2000 は fp2000 が 1,580、fp_base2000 が 1,581。 fp2000 スコアと fp_base2000 スコアが逆転している。 逆転するなら fp2000の設定 = fp_base2000 の設定にしときゃいいのに。
IBM POWER5+ 1900MHz の正式なスコアが出たので、 int2000 が 1,513 で fp2000 が 3,030 となる。 FP 性能はあいかわらず速い。
ライバルの富士通の SPARC64 V 2160MHz は 1890MHz から int2000 が 1,345 → 1,620 に、 fp2000 は 1,803 → 2,236 に。 1890MHz が Sun Studio8 + Fujitsu Parallelnavi 2.3 だったが、 2160MHz では Sun Studio 11 に。 Sun と富士通のサーバ統合で、Sun のコンパイラが SPARC64 をサポートしたのが効いたのかしら?
他、Intel 系のプロセッサをいくつか更新。 面倒なので下の URL を見てね。
更新
2/3 (金)
新年会%旧暦仕様 兼 節分会 兼 N404号室解散会
会社の大幅な職制変更で、 職場の部屋の面子も今年度末でバラバラに。 お別れ会を兼ねて中華街で遅い新年会をやりますた。 場所は中国維揚料理 三蔵飯店 (横浜チャイナタウン、ぐるなび)。
これまで上海料理というのは食べたことがなかったが、 どの皿が上海料理なのかよくわからん。
お店の前 |
|||
五種前菜盛り合わせ (クラゲ、チャーシュー、ピータン、蒸しどり、ユバ巻) |
車海老のチリソース |
牛肉のXO醤炒め |
生ガニの卵炒め |
北京ダック |
豚肉の角煮 |
挟んだところ |
|
カニ肉とダイコンの煮付け |
フカヒレの煮込みスープ |
アンニンドーフ |
おまけ写真
時事
サウジアラビア西部のドゥバハからエジプトのサファーガ港へ向かうフェリー「アル・サラーム98」が沈没。 乗客・船員を含めて1400人超が乗船。救出されたのは300人。
2/1 (水)
浮動小数点演算の実装
会社に IEEE 754 の浮動小数点をソフトエミュレーションする場合の アルゴリズムを探している人がいる。 いい本がないか聞かれるが即答できず。 Hack's Delight には演算方法の詳細は載っていないようだ。 Art of Programming にありそうな気もするけど、 周りの人も持ってないからなぁ。
権利関係でそれはできない?
# Itanium?
権利関係が分からないので、見てもいいのか分かりませんが。
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/softfloat/
(の例えば bit32/softfloat.c) の方にあります。
ついでにコメントの日付が間違ってすんませんでした。
やはりソースコードを読むのが早いですかねェ。
今回の件は、会社の人が弄っている組み込む向け Linux の浮動小数点演算エミュレータに誤差が生じているのがきっかけです。彼はこの誤差を IEEE 754 規格に合うように修正したくて、リファレンスになる教科書的な本を探していました。
権利関係のことは良く分からんのですがコードをコピーするという話でもないので、彼には fp エミュの実装を何通りか読んでみることを勧めてみます。
http://docs.sun.com/source/806-4847/ncg_math.html#586
pdf版もあります。ieeeフォーマットについて結構詳しく書いてあると思います。
#include
#define INL_REGID_APITC 3116
unsigned __int64 __getReg(int whichReg);
#define rditc() __getReg(INL_REGID_APITC)
と定義して、rditc()で測定区間を挟んで、サイクルで
カウントしたほうがより正確かも、、ですね。
unsigned long rditc() {
unsigned long result = -1;
do {
__asm__ __volatile__ ("mov %0=ar.itc" : "=r"(result) :: "memory");
} while (__builtin_expect ((int) result == -1, 0));
return result;
}
〇 Null pointer exception からシグナルハンドラに到達するまでが 2032 サイクル。
// シグナルハンドラ
static void signal_handler(int sig, siginfo_t* sig_info, void* sig_data) {
counter += rditc() - tmp;
membar();
siglongjmp(return_point, 1);
}
// メイン
for (i = 0; i
tmp = rditc();
membar();
*p = 0;
}
}
printf("%lu\\n", counter/REPEAT);
〇 sigsetjmp から siglongjmp で戻ってくるところまでが 2481 サイクル。
// メイン
tmp = rditc();
if (sigsetjmp(return_point, 1) == 0) {
membar();
*p = 0;
}
counter += tmp;
membar();
printf("%lu\\n", counter/REPEAT);