基本的に落書き帳/メモ帳/備忘録なので、 わりと間違っていたり、 数分後とか後日とかに見たら、 いきなり消えていたり書き換わっていたりとかあります。
店頭にあった。1冊のみ。
各種計算機のベンチマーク結果
を更新。
Core i5-450M にて、姫野ベンチを採ってみた。
速いのだか遅いのだかさっぱり分からない結果が出た。
一ヶ月以上、
バグも発見されなければ新ネタも思いつかなかった。
珍しい。
今は細々とコーパス用変換結果を溜めているのみ。
でも、今のペースだと目標まであと1〜2年はかかるし……。
mozc は、 uim-mozc が正式リリースかつ ports入りを果たすまで手を出す気無し。 scim, ibus は文節区切りが表示されないので好みに合わない。 でも、uim-mozc が portsに入っても 乗り換えが面倒になって そのまま uim-anthy(uim-xim) を使い続けそうだ。
BerkeleyDB のトランザクション処理やロック処理の C/C++ でのサンプルが web で検索しても見つからなかったので、 自分で書いてさらしてみる。 bdb の source tar ball の example_c/ 以下に 多少はサンプルが有るのですがね。
/**@file * Test of the bdb *@brief BerkeleyDB のテスト *@date Sun,07 Oct,2012 - Mon,08 Oct,2012 *@author Copyright(C)2012 G-HAL */ #include#include #include #include #include #include #define DATABASE_DIR "test_dir.db/" #define DATABASE_FILE "test.db" #define BUFSIZE 1024 int main() { int err_ret = 0; int ret; DB_ENV* dbenv; ret = db_env_create(&dbenv, 0); if (0 != ret) { fprintf(stderr, "db_env_create: %s\n", db_strerror(ret)); err_ret = ret; goto ERR_RET; } ret = dbenv->open(dbenv, DATABASE_DIR, DB_THREAD | DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN, 0664); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->open"); err_ret = ret; goto ERR_RET; } ret = dbenv->set_flags(dbenv, DB_TIME_NOTGRANTED, 1); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->set_flags"); err_ret = ret; goto ERR_ENV_CLOSE; } ret = dbenv->set_timeout(dbenv, 8000, DB_SET_LOCK_TIMEOUT); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->set_timeout"); err_ret = ret; goto ERR_ENV_CLOSE; } ret = dbenv->set_timeout(dbenv, 8000, DB_SET_TXN_TIMEOUT); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->set_timeout"); err_ret = ret; goto ERR_ENV_CLOSE; } u_int32_t locker; ret = dbenv->lock_id(dbenv, &locker); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->lock_id"); err_ret = ret; goto ERR_ENV_CLOSE; } DB_LOCK lock; { static char* const buf_lock_dbt = "ALL_LOCK"; DBT lock_dbt; memset(&lock_dbt, 0, sizeof(lock_dbt)); lock_dbt.data = buf_lock_dbt; lock_dbt.size = strlen(lock_dbt.data); ret = dbenv->lock_get(dbenv, locker, 0 /* DB_LOCK_NOWAIT */, &lock_dbt, DB_LOCK_WRITE, &lock); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->lock_get"); err_ret = ret; goto ERR_LOCK_ID_FREE; } } DB* dbp; ret = db_create(&dbp, dbenv, 0); if (0 != ret) { dbenv->err(dbenv, ret, "db_create"); err_ret = ret; goto ERR_LOCK_PUT; } DB_TXN* txnp; ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->txn_begin"); err_ret = ret; goto ERR_LOCK_PUT; } ret = dbp->open(dbp, txnp, DATABASE_FILE, NULL, DB_HASH, DB_THREAD | DB_CREATE, 0664); if (0 != ret) { dbp->err(dbp, ret, "dbp->open(%s)", DATABASE_FILE); err_ret = ret; ret = txnp->abort(txnp); if (0 != ret) { fprintf(stderr, "txnp->abort: %s\n", db_strerror(ret)); } goto ERR_ENV_CLOSE; } ret = txnp->commit(txnp, 0); if (0 != ret) { fprintf(stderr, "txnp->commit: %s\n", db_strerror(ret)); } ret = dbp->sync(dbp, 0); if (0 != ret) { dbp->err(dbp, ret, "dbp->sync"); } { char buf[BUFSIZE]; bool dirty = false; while (!feof(stdin)) { fprintf(stdout, "key,data\n"); buf[0] = '\0'; const char* const buf_fgets = fgets(buf, sizeof(buf), stdin); if (NULL == buf_fgets) { err_ret = 0; if (dirty) { fprintf(stdout, "txnp->abort\n"); ret = txnp->abort(txnp); if (0 != ret) { fprintf(stderr, "txnp->abort: %s\n", db_strerror(ret)); } } break; } buf[sizeof(buf)-1] = '\0'; char* const buf_key = buf; char* buf_dat = strchr(buf, ','); if (NULL != buf_dat) { *buf_dat = '\0'; ++ buf_dat; } else { if (dirty) { fprintf(stdout, "txnp->commit\n"); ret = txnp->commit(txnp, 0); if (0 != ret) { fprintf(stderr, "txnp->commit: %s\n", db_strerror(ret)); } ret = dbp->sync(dbp, 0); if (0 != ret) { dbp->err(dbp, ret, "dbp->sync"); } dirty = false; } continue; } DBT key, data; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.data = buf_key; key.size = strlen(key.data); data.data = buf_dat; data.size = strlen(data.data); if (!dirty) { ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->txn_begin"); } } ret = dbp->put(dbp, txnp, &key, &data, DB_NOOVERWRITE); if (0 != ret) { dbp->err(dbp, ret, "db->put"); if (DB_KEYEXIST != ret) { err_ret = ret; break; } } dirty = true; } } ERR_CLOSE: ret = dbp->close(dbp, 0); if (0 != ret) { dbp->err(dbp, ret, "dbp->close"); } ERR_LOCK_PUT: ret = dbenv->lock_put(dbenv, &lock); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->lock_put"); } ERR_LOCK_ID_FREE: ret = dbenv->lock_id_free(dbenv, locker); if (0 != ret) { dbenv->err(dbenv, ret, "dbenv->lock_id_free"); } ERR_ENV_CLOSE: ret = dbenv->close(dbenv, 0); if (0 != ret) { fprintf(stderr, "dbenv->close: %s\n", db_strerror(ret)); /* dbenv->err(dbenv, ret, "dbenv->close"); */ } ERR_RET: return err_ret; } /* [ End of File ] */
「I18N(Internationalization) GearHead」
スレ14号機 72氏、89氏 指摘の件、
「暗殺(中略)毎ターン話しかけられてすごくうざい」。
TS_XRAN_aU--_Assassin.txt の会話終了フラグが
誤:「V= 1 2」
→
正:「P= 1 2」
。
うっかり OO を LO に更新したら、 make に5時間 3.2GiB 消費してしまった。
誤:じょういげだつ
正:じょういかたつ
alt-cannadic には両方入っていた。
正:いっせいちだい
2時間ばかり書き物をしていたが、 Anthy のログが 200件しか貯まらなかった。 昔と比べタイプ速度がかなり落ちているのかな。
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
試験版更新:
安定版,旧安定版へのバックポートは、
もっと例文を貯めてからの予定。
多分、今のペースだと目標まであと1〜2年はかかる見込み……。
「|××や|」が1単語で出ない事に気づいた。
「|知らないや|」とか「壊れたや」などが
「|知らない|や|」とか「|壊れた|や|」になる。
方言かな? 口語かな?
って Wed,18 Nov,2009 で既出だった。
「理解できつつ」ってどこで文節を区切るべきなのだろう?
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
試験版更新:
安定版,旧安定版へのバックポートは、
もっと例文を貯めてからの予定。
過去ログから例文を再構築すると言う事をやって
一挙に大量追加をしたので、目標まで残り約400件。
この追加が済むと一挙に例文件数3割増になる見込み。
# ただ、試験的に使ってみた感じだと
なにがしかが改善された感じは全くありません。
2012年3月頃の alt-cannadic, alt-depgraph, angie から 単漢字辞書が CC BY-SA 2.1 になっている事の注意表記を忘れていた。
更新して、 実ディスクから VMWare のイメージへの複写を行おうとしたのだが、 まさかの単純操作ミス(ディレクトリ指定を間違えた)で、 実ディスクとイメージ両方の /var を破壊してしまった(泣。
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
試験版更新:
過去ログ10年分から抽出した結果。
せっかく抽出作業をしたので残しておくテスト。
じょうめん T35 上面 しゃろ T35 斜路 めいばん T35 銘板 すいじゅんてん T35 水準点 べつあん T35 別案 しんどうし T35 振動子 「|振動|子|」(|しんどう|し|)にすべきか? していし T35 指定子 「|指定|子|」(|してい|し|)にすべきか? たいけつしょく T15 対決色 「|対決|色|」(|たいけつ|しょく|)にすべきか。 ひこ T35 被呼 「|被|呼|」(|ひ|こ|)にすべきか。 じょそう T30 除装 ほとんど使わない。imported_words_default.d で済ますべきか? めいはいはくしょく T35 明灰白色 ほとんど使わない。imported_words_default.d で済ますべきか? やきてついろ T35 焼鉄色 ほとんど使わない。imported_words_default.d で済ますべきか? あんりょくしょく T35 暗緑色 ほとんど使わない。imported_words_default.d で済ますべきか? おうとうしょく T35 黄橙色 ほとんど使わない。imported_words_default.d で済ますべきか? こくてつしょく T35 黒鉄色 ほとんど使わない。imported_words_default.d で済ますべきか? こうろ T35 光路 専門用語。imported_words_default.d で済ますべきか? かかそくど T35 加加速度 専門用語。imported_words_default.d で済ますべきか? かそくへんかど T35 加速変化度 専門用語。imported_words_default.d で済ますべきか? けいこうかん T35 蛍光管 専門用語。imported_words_default.d で済ますべきか? たちか T30 多値化 専門用語。imported_words_default.d で済ますべきか? えるふぃんかん T35 エルフィン管 専門用語。imported_words_default.d で済ますべきか? かいじ T35 界磁 専門用語。imported_words_default.d で済ますべきか? かいてんし T35 回転子 専門用語。imported_words_default.d で済ますべきか? こていし T35 固定子 専門用語。imported_words_default.d で済ますべきか? かんごう T11 嵌合 専門用語。imported_words_default.d で済ますべきか? きょうしょう T15 共晶 専門用語。imported_words_default.d で済ますべきか? きりくしゃ T35 軌陸車 専門用語。imported_words_default.d で済ますべきか? げっさ T35 月差 にっさ T35 日差 そうとう T35 双投 業界用語。imported_words_default.d で済ますべきか? たんとう T35 単投 業界用語。imported_words_default.d で済ますべきか? しゅんてい T30 瞬停 業界用語。imported_words_default.d で済ますべきか? けつげん T35 結言 業界用語。imported_words_default.d で済ますべきか? たがいせん T15 互先 業界用語。imported_words_default.d で済ますべきか? なかね T35 仲値 業界用語。imported_words_default.d で済ますべきか? はざい T15? 端材 業界用語。imported_words_default.d で済ますべきか? そうりん T30 装輪 業界用語。imported_words_default.d で済ますべきか? かたはいれ T10 片端入れ 業界用語。imported_words_default.d で済ますべきか? りょうはいれ T10 両端入れ 業界用語。imported_words_default.d で済ますべきか? りょうおち T10 両落ち 業界用語。imported_words_default.d で済ますべきか? ? T10 両端落とし 業界用語。imported_words_default.d で済ますべきか? しながしりょう T35 品貸料 業界用語。imported_words_default.d で済ますべきか? きりこ T35 切り粉 業界用語。imported_words_default.d で済ますべきか? きりこ T35 切粉 業界用語。imported_words_default.d で済ますべきか? さしなり T10 指成 業界用語。imported_words_default.d で済ますべきか? ひけさし T10 引指 業界用語。imported_words_default.d で済ますべきか? ひけなり T10 引成 業界用語。imported_words_default.d で済ますべきか? ふなり T10 不成 業界用語。imported_words_default.d で済ますべきか? よりさし T10 寄指 業界用語。imported_words_default.d で済ますべきか? よりつき T10 寄付 業界用語。imported_words_default.d で済ますべきか? よりなり T10 寄成 業界用語。imported_words_default.d で済ますべきか? かんかん T30 観艦 ほとんど使わない。imported_words_default.d で済ますべきか? しょうい ? 焼夷 ほとんど使わない。imported_words_default.d で済ますべきか? てきほう T35 敵堡 ほとんど使わない。imported_words_default.d で済ますべきか? しんち ? 信地 クローラ てっこう T15 徹甲 ほとんど使わない。imported_words_default.d で済ますべきか? りゅうさん T15 榴散 ほとんど使わない。imported_words_default.d で済ますべきか? じゅうりん T15 従輪 せいきょ ? 正距 地図投影法 せいてい T30 整定 専門用語。imported_words_default.d で済ますべきか? せいてん T30 正転 だっちょう T30 脱調 専門用語。imported_words_default.d で済ますべきか? ていばい T30 逓倍 専門用語。imported_words_default.d で済ますべきか? へんぱ T30 偏波 専門用語。imported_words_default.d で済ますべきか? ほよう T35 歩容 専門用語。imported_words_default.d で済ますべきか? そうちゅう T35 双柱 ほとんど使わない。imported_words_default.d で済ますべきか? ぞうそく T30 増速 減速 g-jiritu-0208.t:ちょうしゃく #T35*200 長尺 T15? どうじ T15 同次 専門用語。imported_words_default.d で済ますべきか? ついじゅく T30 追熟 果物 りゅうがん T35 竜眼 果物 りゅうがん T35 龍眼 果物 さかふねいし T35 酒船石 遺跡 じょうこう JS 条項 T35 だけで十分か?望まない変換との関連も有るし。どうしよう。 こうほ JS 候補 T35 だけで十分か?望まない変換との関連も有るし。どうしよう。 くぶん JS 区分 T30 だけで十分か?望まない変換との関連も有るし。どうしよう。 じゅん JS 巡 いらないかも。望まない変換との関連も有るし。どうしよう。 こう JS 行 銀行を数える時。T35 だけで十分か?望まない変換との関連も有るし。どうしよう。 へんせい JS 編成 T30 だけで十分か?望まない変換との関連も有るし。どうしよう。
「I18N(Internationalization) GearHead」
スレ14号機 360氏 指摘の件、 『vikkiの 「もし十勝することが出来たら、特別な商品がでるの。」 ってセリフ、「特別な賞品」の誤変換なんじゃ…』。
「10勝」,「十勝」とバラバラだったので、 「10勝」に統一。
「I18N(Internationalization) GearHead」
「UTF-8 GearHead-2」
上記2つのページにライセンス表記を忘れている事に気付いて慌てて修正。
ヨドバシカメラにて、
Panasonic DVD-RAM x2〜x3 ヨドバシカメラモデル製造終了、
の Pop が出ていた。
パナだから終了なのか、
BD にシフトしているから終了なのか、
それとも別の何かなのか、
どうなのだろう。
正:しとつ
SQLite をC言語から使う時、
いちいちプレーンテキストの SQL から実行するのは
すごい無駄で遅くなる様な気がずっとしていた。
そういう時はプリペアードステートメントと言う物を使うらしい。
データベースのベンチマークを採ってみた。
・Anthy 拙作パッチ用の学習データ 75394件 4.6MB を、 各種データベースに全件出力/全件入力してみた時の所要時間。 ・関連ファイルが全てディスクキャッシュ上に有る状態で計測。 ・ファイルシステムは UFS2+softupdate+gjournal。 ・各3回計測し、中央値を掲載。 cat(列のパース無し) 全件書き込み 該当機能無し 全件シーケンシャル読み出し 0.015u 0.047s 0:00.05 100.0% 84+224k 0+35io 0pf+0w ランダム読み出し10000件 該当機能無し Anthy 拙作パッチ(列のパース有り) 全件入出力 4.977u 0.243s 0:05.28 98.6% 25+193k 1+50io 0pf+0w 全件シーケンシャル読み出し 2.768u 0.243s 0:03.01 99.6% 26+194k 0+0io 0pf+0w ランダム読み出し10000件 該当機能無し Berkeley DB - bdb(列のパース無し) 全件書き込み 2.666u 1.164s 0:03.94 96.9% 5+168k 366+637io 0pf+0w 全件シーケンシャル読み出し 1.869u 0.031s 0:01.90 99.4% 15+168k 0+0io 0pf+0w ランダム読み出し10000件 0.031u 0.100s 0:00.13 100.0% 4+162k 0+8io 0pf+0w SQLite3(列のパース無し)全件書き込み 4.372u 53.481s 1:30.83 63.6% 10+166k 0+909387io 0pf+0w全件書き込み 0.435u 0.087s 0:00.52 98.0% 10+170k 0+108io 0pf+0w 全件シーケンシャル読み出し 0.095u 0.047s 0:00.13 100.0% 60+193k 0+35io 0pf+0w ランダム読み出し10000件 14.587u 0.023s 0:14.61 99.9% 10+167k 0+4io 0pf+0w KyotoCabinet(列のパース無し) Sat,24 Nov,2012 追記 全件パースしつつコミットしない 0.345u 1.036s 0:01.49 91.9% 1247+174k 1+102io 0pf+0w 全件書き込み 0.197u 0.546s 0:00.80 91.2% 1261+175k 1+416io 0pf+0w 全件シーケンシャル読み出し 0.103u 0.015s 0:00.11 100.0% 1254+207k 0+0io 0pf+0w ランダム読み出し10000件 0.045u 0.015s 0:00.06 83.3% 1442+251k 0+4io 0pf+0w TokyoCabinet-Hash(列のパース無し) Sun,25 Nov,2012 追記 全件書き込み 0.076u 0.410s 0:00.51 94.1% 10+173k 0+970io 0pf+0w 全件シーケンシャル読み出し(tchdbmgr) 0.087u 0.015s 0:00.10 90.0% 28+190k 0+0io 0pf+0w 全件シーケンシャル読み出し 0.204u 0.015s 0:00.21 100.0% 5+176k 0+0io 0pf+0w ランダム読み出し10000件 0.043u 0.025s 0:00.06 100.0% 10+176k 0+0io 0pf+0w ランダム読み出し10000件(optimize) 0.026u 0.008s 0:00.03 66.6% 16+264k 0+0io 0pf+0w TokyoCabinet-BTree(列のパース無し) Sun,25 Nov,2012 追記 全件書き込み 0.247u 0.063s 0:00.31 96.7% 10+171k 0+14io 0pf+0w 全件シーケンシャル読み出し 0.122u 0.032s 0:00.15 100.0% 30+167k 0+0io 0pf+0w ランダム読み出し10000件 0.069u 0.062s 0:00.13 92.3% 10+176k 0+4io 0pf+0w ランダム読み出し10000件(optimize) 0.079u 0.055s 0:00.13 92.3% 11+187k 0+0io 0pf+0w
SQLite3 の1分30秒かかっている方は、 BEGIN 〜 COMMIT でトランザクションくくるのを忘れていた。
Anthy 拙作パッチの全件シーケンシャル読み出しは、 メモリ管理まわりとディスク読み出しがボトルネックになっている。
Berkeley DB は速そうだが、 列のパースを追加すると、 多分 Anthy 拙作パッチと同程度か遅くなりそうな気がする。
SQLite3 は、ランダム読み出しが想像よりも1桁以上遅かった。
Berkeley DB と1桁以上差が付くとは思わなかった。
となると、Anthy 拙作パッチの学習データベースは、 これ以上いじっても速くならないか……。
Sat,24 Nov,2012 追記:
京都キャビネットのこの速度は一体何ですか……。
ライセンスを確認したら GPLv3 だった。
GPLv3 だと呼出側も GPLv3 に固定されるんだっけ?
面倒に巻き込まれたくないので
呼出側を BSDライセンスにする事が可能な方が望ましいのだが、
商用ライセンスは 100万円から御相談ですか……。
Sun,25 Nov,2012 追記:
東京キャビネットなら LGPL v2.1 らしい。
これなら呼出側を BSDライセンスにできるかな……。
京都キャビネットと比べても遜色無い速度だし。
printf("%.*s", (int)len, (char*)str); なんて知らなかったよ……。
Firefox 15 までは
sb-ssl.google.com から鍵を取得して
データ取得は何処だか忘れた
urlclassifier3.sqlite に保管していたらしいが、
Firefox 17 では
sb-ssl.google.com から鍵を取得して
safebrowsing.clients.google.com:80 からデータを取得して
safebrowsing/ に保管、
に変わったっぽい。
ぽいっと言うのは、裏付けを取っていないから。
web で検索してもわからなかったので、
おもむろにエディターを立ち上げ(以下略)。
hacklib.c
スマートだわ……。
でも、「E7n平面座標系」がいまだ不明。
Tue,20 Nov,2012 のデータベースのベンチマークに 京都キャビネットを追加。
Tue,20 Nov,2012 のデータベースのベンチマークに 東京キャビネットを追加。
vim用 文字コード自動判別マクロ、 「q:」でステータスラインがこけるバグを修正。
占いクッキー 100文。
anthy-9100h.alt-depgraph.patch13-testing : 8.478u 1.952s 0:10.43 99.9% 30+193k 0+114io 0pf+0w
株に関して、 「5銘柄」とか「10銘柄」とか言うけれど、 「銘柄」(めいがら)は助数詞なのだろうか。
占いクッキー 100文。
anthy-9100h.alt-depgraph.patch13-testing : 5.584u 2.055s 0:07.64 99.8% 30+192k 0+30io 0pf+0w 5.651u 1.999s 0:07.69 99.3% 30+193k 0+30io 0pf+0w anthy-9100h.alt-depgraph.patch13-testing.tokyocabinet : 6.156u 3.148s 0:09.58 96.9% 30+193k 0+214io 0pf+0w
学習データをメモリ上に展開して使用する仕様(testing)から、
ディスク上に置いたままアクセスする仕様(testing.tokyocabinet)に
変更してみた。
思っていたよりかは遅くならなくて済んだものの、
Anthy は元が遅めだからなぁ……。
体感だと Mozc はもうちっと遅い感じがするけれど。
学習データをディスク上に置いたままにするメリットは。
デメリットは。
それじゃぁ、
共有メモリか何かを使って学習データを同期すれば、
速いのでは、と思うかもしれないけれども。
そうするくらいならサーバクライアントモデルにした方が良いよね。
個別プロセス毎に稼働する仕様から
サーバクライアント方式で稼働する仕様に変更する為に
根本的に作り直すくらいなら
sj3 に乗り換えた方がもっと高速な変換速度が得られる(略)
上記の拙作パッチを作っていたら、
拙作パッチに
gcc -O3 かつ htobe64() や betoh64() が無いシステムでしか発症しない
バグを発見。
gcc -O0 だったり htobe64() や betoh64() が有ると、
発症しない。
2日かかって判明した所によると、
uint8_t buf[8];
uint64_t var;
に対して
(*(uint64_t*)buf) = var;
した時に、
inline 展開した時としない時でメモリアクセスするアドレスが違う。
なんじゃそりゃ。
(*(uint64_t*)&(buf[0])) = var;
とかすると、
inline 展開した時としない時でメモリアクセスするアドレスが同じになった。
なんじゃそりゃ。
Sat,08 Dec,2012の続き。
別の所をいじっていたら、
(*(uint64_t*)&(buf[0])) = var;
でも挙動不審になった。
今度は、問題の箇所の直前で
const volatile uint8_t tmp0 = (*(uint8_t**)ptr)[0];
とかすると、期待通りの動作をする様になった。
なんじゃそりゃ。
Sat,08 Dec,2012、 Mon,10 Dec,2012の続き。
web で関連ありそうな記事を見つけた。 猫科研究所(felid labo) - gcc option かなぁ? ホワット・ア・ワンダフル・ワールド - strict aliasing rule かな。 type-punned pointer らしい。
-fno-strict-aliasing にしたら、
-O3 にて変な事しなくても期待通りの動作をする様になった。
でも、利用者が必ず -fno-strict-aliasing してくれる事を
期待できないんだよなぁ。
どうしよう。
「union 使え」か。
-Wstrict-aliasing=1 にしても何も言ってくれない。
Wed,12 Dec,2012に続く。
Sat,08 Dec,2012、 Mon,10 Dec,2012、 Tue,11 Dec,2012の続き。
整理してみよう。
そもそもの事の起こりは、 ファイル入出力におけるエンディアン変換を static inline な関数にまとめた所から始まる。
雰囲気としては以下の様な感じ。
static inline uint8_t memread_uint8(const void** const ptr, size_t* const len) { const uint8_t data = **(const uint16_t* const* const)ptr; const uint8_t ret = data; ++ (*(const uint8_t** const)ptr); (*len) -= 1; return ret; } static inline uint16_t memread_uint16(const void** const ptr, size_t* const len) { const uint16_t data = **(const uint16_t* const* const)ptr; const uint16_t ret = ntohs(data); ++ (*(const uint16_t** const)ptr); (*len) -= 2; return ret; } static inline uint32_t memread_uint32(const void** const ptr, size_t* const len) { const uint16_t data = **(const uint32_t* const* const)ptr; const uint32_t ret = ntohl(data); ++ (*(const uint32_t** const)ptr); (*len) -= 4; return ret; } 中略 static inline void memread_xstr_ucs4(xstr* const msg, const void** const ptr, size_t* const len) { ここでメモリ管理の処理など行っている。省略。 uint16_t str_len = memread_uint16(ptr, len); uint16_t i; xchar* xchar_ptr; for (i = 0, xchar_ptr = msg->str; i < str_len; ++i, ++xchar_ptr) { *xchar_ptr = memread_uint32(ptr, len); } return; }
これを -O2 か -O3 でコンパイルするか、
-O0 や -O1 でも -fstrict-aliasing にしてコンパイルすると、
memread_uint16() や memread_uint32() などの返値が不定になる。
でも memread_uint8() は不定になる事は無い。
-O2 か -O3 でも -fno-strict-aliasing だと、
memread_uint16() や memread_uint32() などの返値は不定にならない。
memread_uint8() も不定になる事は無いそのまま。
static inline な関数定義を extern に変更すると、
これまた返り値は不定にはならない。
これは、 変数 const void** const ptr に対するキャストが type-punned pointer になってしまっている為らしい。 C/C++言語の仕様上は、返値が不定になる方が正しいらしい。
これに対処した、仕様上正しい書き方は以下の様になるらしい。
typedef union { void* vp; uint8_t* u8p; uint16_t* u16p; uint32_t* u32p; uint64_t* u64p; } type_punned_pointer_cast_t; static inline uint8_t memread_uint8(const void** const ptr, size_t* const len) { const uint8_t data = *((const type_punned_pointer_cast_t* const)ptr)->u8p; const uint8_t ret = data; ++ ((type_punned_pointer_cast_t* const)ptr)->u8p; (*len) -= 1; return ret; } static inline uint16_t memread_uint16(const void** const ptr, size_t* const len) { const uint16_t data = *((const type_punned_pointer_cast_t* const)ptr)->u16p; const uint16_t ret = ntohs(data); ++ ((type_punned_pointer_cast_t* const)ptr)->u16p; (*len) -= 2; return ret; } static inline uint32_t memread_uint32(const void** const ptr, size_t* const len) { const uint32_t data = *((const type_punned_pointer_cast_t* const)ptr)->u32p; const uint32_t ret = ntohl(data); ++ ((type_punned_pointer_cast_t* const)ptr)->u32p; (*len) -= 4; return ret; } 中略 static inline void memread_xstr_ucs4(xstr* const msg, const void** const ptr, size_t* const len) { ここでメモリ管理の処理など行っている。省略。 uint16_t str_len = memread_uint16(ptr, len); uint16_t i; xchar* xchar_ptr; for (i = 0, xchar_ptr = msg->str; i < str_len; ++i, ++xchar_ptr) { *xchar_ptr = memread_uint32(ptr, len); } return; }
memread_uint16() や memread_uint32() などにおいて、
ptr をアクセスする際に共用体にキャストして
アクセスする様に変更した。
gcc 拡張としては、
const void** const ptr に
__attribute__((may_alias)) を付けるのでも良いらしいが、
手元で試した所では駄目だった(gcc 4.2.1 20070831 patched [FreeBSD])。
それに、可搬性が無くなり gcc 以外では仕様上不定になってしまう。
こんな所かな。
偉い人(仕様に明るい人)に教えてもらったわけでも無く、
全く同一の例の先人を見つけたわけでも無く、
どことなく似た様な事例の web 記事を見て書いたので、
間違っているかもしれません。
教訓としては、
どうやら C/C++言語のポインタを、
アセンブリ言語のアドレッシングと全く同一に考えてはいけないらしい。
蛇足としては、
最初に inline 展開を禁止すると発症しなくなる事に気付いて、
そこを起点に試行錯誤した為に、
strict aliasing に辿り着くまでに4日遠回りしてしまった。
上述全部に辿り着いて解決するコードに書き換えるまでに
遠回りを含めて1週間かかってしまった。
上述の type-punned pointer のバグ修正予定。
該当するのは……
patch7.2008X16 以降全て。
# ぐへぇ、どうしよう。
コーパスが前回更新時以降に 1500件以上貯まったので、
予定通り、試験版へのコーパス追加および
旧安定版,安定版へコーパスをバックポートの予定。
昨日の type-punned pointer のバグ修正をしていたら、
mmapが使える amd64/i386系にて
学習データのバイナリ形式読み込み時に
エンディアン変換を間違えているバグ発見 orz。
学習データのスコアリング関連が壊れています。
済みませんが 2012Z15版以降に更新の上、
学習データを削除して下さい。
学習データの削除方法: /bin/rm ${HOME}/.anthy/last-record*
「かな漢字変換 anthy で、個人用学習データを活用して、変換結果の改善を目指すパッチ」
2012Z14版以前にて、学習データを壊すバグがありました。
済みませんが 2012Z15版以降に更新の上、
学習データを削除して下さい。
学習データの削除方法:
/bin/rm ${HOME}/.anthy/last-record*
更新内容一覧:
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
試験版更新:
2012Z14版以前にて、学習データを壊すバグがありました。
済みませんが 2012Z15版以降に更新の上、
学習データを削除して下さい。
学習データの削除方法:
/bin/rm ${HOME}/.anthy/last-record*
更新内容一覧:
蛇足:
コーパス分量倍増計画完了。
コーパスの件数が原作版 Anthy の2倍になりました。
でも変換結果への影響はあまり無い感触……。
今までのデータ関連の作業でもっとも効果的だったのは
vagus氏の alt-depgraph だったと思う。
安定版更新:
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
2012Z14版以前にて、学習データを壊すバグがありました。
済みませんが 2012Z15版以降に更新の上、
学習データを削除して下さい。
学習データの削除方法:
/bin/rm ${HOME}/.anthy/last-record*
更新内容一覧:
備考:corpus_wb_dic 機能
試験版(testing)に 2012年7月から実装されていた機能。
変換内容の読み仮名がコーパスの例文に一致する(ハッシュが例文と一致する)
時に、
例文と同じ位置の文節区切りを高スコアにします。
原作版 Anthy にも似た様な機能が有りますが、
違いは、
です。
「かな漢字変換 anthy で、個人用学習データを活用して、変換結果の改善を目指すパッチ」
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
更新内容一覧:
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
更新内容一覧:
学習データのバイナリ形式の中身を、 シーケンシャルな記録から、 TokyoCabinet なハッシュデータベース形式に 変更しています。 これにより、 個々の変換が2割程度遅くなる代りに、 学習データの再読み込みが超高速になります。 学習データの再構築の所要時間は4割程度遅くなります。
個々の変換ベンチマーク(変換100文):(Sat,08 Dec,2012より再録) シーケンシャルファイル版 5.651u 1.999s 0:07.69 99.3% 30+193k 0+30io 0pf+0w 東京キャビネット hash 版 6.156u 3.148s 0:09.58 96.9% 30+193k 0+214io 0pf+0w
学習データの再読み込みベンチマーク(再読み込み1回毎): シーケンシャルファイル版 3.059u 0.196s 0:03.25 99.6% 30+193k 0+117io 0pf+0w 東京キャビネット hash 版 0.031u 0.054s 0:00.08 100.0% 27+186k 0+9io 0pf+0w
学習データの再構築ベンチマーク(再構築1回毎): シーケンシャルファイル版 3.059u 0.196s 0:03.25 99.6% 30+193k 0+117io 0pf+0w ← 「学習データの再読み込み」と同じです。 東京キャビネット hash 版 3.382u 0.929s 0:04.68 91.8% 29+190k 0+2593io 0pf+0w
学習データの再読み込みが発生する場面:
学習データの再構築が発生する場面:
考察:
日本語変換に消費した総時間で考えると。
学習データの再読み込み無しに200文ほど変換すると、
シーケンシャルファイル版の方が総時間が少ない。
100文程度で学習データの再読み込みが発生すると、
TokyoCabinet版の方が総時間が少ない。
どちらが良いのだろう。
個々の変換時に 20msec 遅くなっても気にならないが、
再読み込みで数秒単位で遅れると気になるんだよね。
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
更新内容一覧:
2012Z18 にて、 使っていない学習セクションに対しても create にて open していた所を、 学習読み出し/書き込みに応じて readonly-open / rdwr-open する様に 修正。
東京キャビネット形式の使用感。
やっぱりちょっとモッサリする感じ。
……。
あれ、変換確定後にモッサリしている。
入力時や変換時じゃ無い。
って事は東京キャビネットがらみじゃないかな。
それとも東京キャビネットの書き込みロック取得だけで
そんなにモッサリするのだろうか?
intptr_t / uintptr_t って、 どんな時使うのだっけ? void* じゃ駄目な時って?
「多少の縁」は間違いで、正しくは、
袖擦り合うも多生の縁
袖擦り合うも他生の縁
の、どちらか(どちらでもよい)らしい。
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
と言うわけで、「たしょうのえん」を用例辞書に追加。
あと、学習データの TokyoCabinet形式の書き込みモードオープンを、 目一杯遅らせてみた。けれどもラグは変わらなかった。
Ultra Book が流行りなのだろうか。
一時期より非光沢液晶が増えた気がする。
「かな漢字変換 anthy で、個人用学習データを活用して、なんかもう思い付く事を何でもかんでも試してみて、変換結果の改善を目指すパッチ」
ソースコードの書き方をちょっと修正。
動作には全く影響無し。
xUnit、コードカバレッジ。
C0/C1/C2 の事を知った。
あと、テストの実例を知った。
gcov, lcov, CUnit, C++Unit
xUnit は Cutter と言うのが便利そうだ。
C1 は lcov がみやすそうだ。
でも OpenBSD の ports は、
CUnit だけで Cutter や lcov が無いなぁ……。
あれ、
Cutter だと main() が無いからコードカバレッジテストかけられない?
Cutter のリファレンスに
コードカバレッジを出力できるって書いてあった。
LTP - Linux test Projct を使うらしい。
lcov は LTP の成果物らしい。
xUnit や C1 をまともに知らない私がパッチ書いているって、 まともに考えると怖いなぁ……。
FreeBSD の ports から入れた lcov だと、 デフォルトで C0 らしい気がする。 lcov と genhtml に --rc lcov_branch_coverage=true 付けて、 C1 になった。
喉が痛い。
T/O
頭が痛い。
出かけた先で銀行に寄ったら、 窓口のみの支店で、ATM手数料無料の威力を発揮できなかった。
電車にタッチアンドゴーで乗ったら、 振替乗車の時に追加料金取られるじゃないですかー(えー
タッチアンドゴーな IC乗車券って何種類あるのだろう?
鼻水鼻詰まり。