« 2008年09月 | メイン | 2009年05月 »

2009年04月19日

ファイルIOではなくバイト列IO

組込用のIMEを作っている方とお話したことあるのですが、組込用のIMEは ポータビリティを高めるために、いわゆるファイルIOは使っておらず システムからimmutableメモリ領域(システム辞書など)とmutableメモリ領域(ユーザ辞書など) をわたしてもらって使うような仕様になっているそうです。 ファイルIOはポータビリティを考えるといろいろ面倒なことがあるのでなるほどな思いました。

実はこういうバイト列を辞書のシリアライズ先として使うことはプリミティブですが身軽です。 自然言語処理のシステムでは静的な辞書や機械学習結果のモデルをロードすることが多々あります。

自分が何かを作るときは、辞書や学習モデルをバイナリのバイト列として格納し、メモリイメージとして読み込むような設計にしています。

例えば、Dictionary というクラスがあったときには、ファイルから辞書を読み込むような インタフェイス Dictionary::OpenFile(const string &filename) を作るのではなく Dictionary::OpenFromArray(const char *array, size_t size) をまず作ります。 ディクショナリの読み込みも、バイト列 array をメモリイメージとして使い、 ポインタのみでアクセスし、内部でコピーを作りません。これを徹底すると、 システムが使用する辞書のメモリ容量は array_size になることが保証され、 システム全体のサイズの予想がつけやすくなります。

ファイルをオープンする場合は、mmapMapViewOfFile といったファイルを メモリーイメージにマッピングするシステムコールを使います。こうすることで ファイルIOがシステムと分離でき、ポータビリティが高まります。
Mmap mmap;     // mmap, MapViewOfFile をラップしたクラス
mmap.Open("foo.dic");

Dictionary dic;
dic.OpenFromArray(mmap.begin(), mmap.size());

投稿者 taku : 15:27 | トラックバック

2009年04月12日

pubic static はコンピュータに伝える約束事ではない

http://www.atmarkit.co.jp/news/200904/10/matz.html
PerlやRuby、Pythonといったスクリプト言語では、 記述が非常にストレートで端的になる。JavaやC++といった言語では、 「public static void mainなど、コンピュータに伝える約束事が多くて、 やりたいことが頭の中から逃げてしまう。簡潔さは力なのです」(まつもと氏)。 これは書くときだけでなく、読むときにも同様だ。

まつもと氏の記事を読んで、仕事として大規模な共同開発の経験に基づいているのかなと思いました。

publicとかstaticとかconstというのは書く側からすると約束事で めんどいということには同意しますが、毎日のようにコードレビューを している経験からいうと、コードレビューをする側にとってこいうキーワードがあるかないかで全く意味が異なります。メソッドがconstであれば、マルチスレッドでも動くことインスタンスがimmutableであることが分かるし、無ければ注意して使わないといけな いことが分かります。const/staticの変数やクラスがあると、 これは不変なんだなとか実際のコードに落とされたアルゴリズムを読みとくのにも ヒントになります。すなわち、こういうキーワードは「コンピュータにとっての約束事」と言い切れるほど単純ではなく 「読み手」や「ユーザ」とのプロトコルを規定す重要なキーワードになります。

約束事は面倒だと言い切ることは短期的には問題ないかもしれません。 しかし、規模が大きくなったりユーザや開発者が増えると本題ではない些末な仕事が 増える結果となります。たとえば「暗黙の約束」みたいなものをドキュメント化 しないといけなかったり、アンドキュメントな使い方をされたときのユーザの対処 など... こいう本筋ではない仕事を技術的な制約で減らすこと、すなわち自分の仕事とユーザの間にファイアウォールを作ることは自分の本来の仕事に集中するために重要です。public/static などという話は「技術的なファイアウォール」の構築のためのとっかかりです。

投稿者 taku : 13:23 | トラックバック