CRFsuite 0.8 released
CRFsuiteのバージョン0.8をリリースしました.モデルファイルのフォーマットを改良し,異なるアーキテクチャにおけるモデルファイルの互換性を確保しました.つまり,x86のアプリケーション・サーバーでCRFのモデルを学習し,SPARCやPowerPCのマシンでモデルを読み込んで,タグ付けをする,といったことが可能になりました.
バージョン0.7をリリースした直後に,Ultra SPARC IIIi上のサーバーで,モデルの読み込み時にクラッシュする問題が報告されました.この問題をデバッグしてみると,4バイトでアライメントされていないメモリアドレスからDWORDの値を読み出すところで,プロセッサ例外が発生することを突き止めました.x86のプロセッサはどんなアドレスからでもDWORDの値を読み出せるという,至れり尽くせりの環境なので,この問題を見逃していました.
そもそも,CRFsuiteのモデルファイルでは,DWORDの値のバイトオーダーすら実行環境依存で,big endianもしくはlittle endianのいずれかに統一する取り決めをしていませんでした.そこで,今回の問題を修正するにあたって,モデルファイル内の数値のバイトオーダーをlittle endianに統一する改訂を行いました.このため,モデルファイルの互換性は失われ,バージョン0.8で0.7以前で作られたモデルファイルを読み込むことは出来ません.
ちなみに,バイトオーダーに依存せずにDWORDの値を読み書きするコードは,以下のようになります.
static void write_uint32(FILE *fp, uint32_t value)
{
uint8_t buffer[4];
buffer[0] = (uint8_t)(value & 0xFF);
buffer[1] = (uint8_t)(value >> 8);
buffer[2] = (uint8_t)(value >> 16);
buffer[3] = (uint8_t)(value >> 24);
fwrite(buffer, sizeof(uint8_t), 4, fp);
}
static void read_uint32(uint8_t* buffer, uint32_t* value)
{
*value = ((uint32_t)buffer[0]);
*value |= ((uint32_t)buffer[1] << 8);
*value |= ((uint32_t)buffer[2] << 16);
*value |= ((uint32_t)buffer[3] << 24);
}
ビットシフトを多用してまどろっこしいですが,このように実装するとコンパイルする環境のバイトオーダーをconfigureスクリプトで検出しなくて済みます.バイナリ形式でI/Oをやるときの常套手段ですね.
64ビットのdouble値にもバイトオーダーがあるのですが,もはやビットシフトは使えないので,いったん64ビットの整数値(uint64_t)に変換し,無理矢理doubleにキャストしています.ARMの一部のプロセッサでは,doubleを2つのDWORDに分解し,各DWORDはlittle endian,2つのDWORD値はbig endianで並べられるという特殊なバイトオーダーが採用されているらしいですが,そういうプロセッサで現在のコードが正しく動作するかは調べていせん.ARMでCRFsuiteを動かすことは,ほとんどあり得ないと思うので,実用上は問題がないと思いますが,こういうCPUのダーティーな部分を知ってしまうと,嫌な感じですね.
トラックバック URL :
コメント (0)