<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:image="http://pirl.org/rss/1.0/modules/image/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel rdf:about="http://dsas.blog.klab.org/">
<title>DSAS開発者の部屋</title>
<link>http://dsas.blog.klab.org/</link>
<description>
</description>
<dc:language>ja</dc:language>
<admin:generatorAgent rdf:resource="http://blog.livedoor.com/?v=2.0" />
<image rdf:resource="http://image.profile.livedoor.jp/icon/klab_gijutsu2_60.gif"/>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com" />
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51563483.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51500856.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51494587.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51491918.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51483496.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51472145.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51466043.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51456004.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51434186.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51423317.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51395944.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51393628.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51390187.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51389536.html" />
  <rdf:li rdf:resource="http://dsas.blog.klab.org/archives/51389200.html" />
 </rdf:Seq>
</items>
</channel>
<image rdf:about="http://image.profile.livedoor.jp/icon/klab_gijutsu2_60.gif">
 <title>DSAS開発者の部屋</title>
 <link>http://dsas.blog.klab.org/</link>
 <url>http://image.profile.livedoor.jp/icon/klab_gijutsu2_60.gif</url>
</image>
<item rdf:about="http://dsas.blog.klab.org/archives/51563483.html">
<title>ApacheのアクセスログをMessagePack形式で出力するためのモジュールを作りました</title>
<link>http://dsas.blog.klab.org/archives/51563483.html</link>
<description>
Apacheモジュールのログ出力、こんどはMessagePack版を作成しました。続いてはこちらをご紹介します。



Apacheのアクセスログを使い、ユーザアクセスの集計やパターン解析などというのは一般にどこでもやられていることだと思います。通常のアクセスログはテキストファイ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-12-22T17:39:41+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<p>
Apacheモジュールのログ出力、こんどはMessagePack版を作成しました。続いてはこちらをご紹介します。
</p>

<p>
Apacheのアクセスログを使い、ユーザアクセスの集計やパターン解析などというのは一般にどこでもやられていることだと思います。通常のアクセスログはテキストファイルなので、集計を行うためにスクリプト上で扱える変数・オブジェクト化が必要になりますね。1行ごとの各ログ項目を取り出すのに正規表現を使ったり、cutやawkなどを使い空白で分割するなど、色々工夫されていることと思います。
</p>

<p>
今回、MessagePack版のアクセスログ出力をやってみようと思い立ったのは、アクセスログをあらかじめ構造化済みの状態で保存しておければ、読み込みの際の解析する手間を省くことで解析処理の高速化が期待できるのではないか、そう考えたためです。MessagePackであれば、PythonやRubyはじめ様々なスクリプト言語でのバインディングを備えており、取り扱いも簡単ですから、ファイル読み込みからログデータの取り出しまでを速やかに行い、その分集計処理の実装に集中することができるわけです。また、時折イレギュラー的に長かったり、予期しない文字がリクエストに入る等したためにログ解析の正規表現がエラーになったりすることがありますが、構造化済みの形式で保存するのであれば、この問題も回避できます。
</p>

<p>
何より、元々構造化されたデータがアクセスログ上では一度文字列になり、これを解析する時に再
度解釈処理されるという二度手間になっているわけで、テキストデータ化せずデータ構造を保った
バイナリとしておくのはこの手間を回避する目的も持っています。
</p>

<p>
ソースはこちらです。<br>
→<a href="http://log.blog.klab.org/support/mod_log_msgpack/mod_log_msgpack-0.1.0.tar.gz">http://log.blog.klab.org/support/mod_log_msgpack/mod_log_msgpack-0.1.0.tar.gz</a>
</p>

＊＊＊

<p>
それでは、実際にどのような変更を加えたのでしょうか。モジュールの中身を見てみましょう。
</p>

<p>
mod_log_msgpackは、従来型のログ出力モジュールであるmod_log_configからその多くを受け継いでいます。mod_log_configの構造がそのまま、mod_log_msgpackにも当てはまるとお考えください。
</p>

<p>
mod_log_configは、起動直後にLogFormatで定義された書式文字列を読み込み、アクセスログに出力する一行分の内容を定義します。例えば、
</p>

<pre class="terminal">
LogFormat "%h %l %u %t \"%r\" %&gt;s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
</pre>

<p>
このようなログ書式の指定があったとします。mod_log_configは、このディレクティブを解釈して下記のような内部的なデータ構造に分解して落とすのです。<a href="http: //httpd.apache.org/docs/2.2/ja/mod/mod_log_config.html#formats">http:
//httpd.apache.org/docs/2.2/ja/mod/mod_log_config.html#formats</a> を参考にしながら、当てはめてみるとこうなります。
</p>

(mod_log_config)

<table>
<tr>
<td style="border-top: 1px solid;"><tt>%h</tt></td><td style="border-top: 1px solid;">リモートホスト(を出力する関数をコールバック)</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" "</tt></td><td style="background-color: #eeeeee;">空白</td>
</tr>
<tr>
<td><tt>%l</tt></td><td>(identdからもし提供されていれば)リモートログ名</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" "</tt></td><td style="background-color: #eeeeee;">空白</td>
</tr>
<tr>
<td><tt>%u</tt></td><td>リモートユーザ</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" "</tt></td><td style="background-color: #eeeeee;">空白</td>
</tr>
<tr>
<td><tt>%t</tt></td><td>リクエストを受け付けた時刻</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" \""</tt></td><td style="background-color: #eeeeee;">空白＋「"」(ダブルクオテーション)</td>
</tr>
<tr>
<td><tt>%r</tt></td><td>リクエストの最初の行</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>"\" "</tt></td><td style="background-color: #eeeeee;">「"」＋空白</td>
</tr>
<tr>
<td><tt>%&gt;s</tt></td><td>最後のステータス</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" "</tt></td><td style="background-color: #eeeeee;">空白</td>
</tr>
<tr>
<td><tt>%b</tt></td><td>レスポンスのバイト数。HTTPヘッダは除く。</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>" \""</tt></td><td style="background-color: #eeeeee;">空白＋「"」(ダブルクオテーション)</td>
</tr>
<tr>
<td><tt>%{Referer}i</tt></td><td>Referer:ヘッダの内容</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>"\" \""</tt></td><td style="background-color: #eeeeee;">「"」＋空白＋「"」</td>
</tr>
<tr>
<td><tt>%{User-agent}i</tt></td><td>User-agent:ヘッダの内容</td>
</tr>
<tr>
<td style="background-color: #eeeeee;"><tt>"\""</tt></td><td style="background-color: #eeeeee;">「"」</td>
</tr>
</table>

<p>
このように、%?の箇所とそれ以外(空白等、置き換えない文字列)とでそれぞれ区切り、小片に分けられます。%で始まる項目は対応するコールバック関数を通し、指定のリクエスト情報を文字列に変換します。つまり、リクエスト情報は一旦LogFormatの項目数分(今回18個)の部分文字列に変換され、最後にこれらをすべて連結してログ1行分として出力しています。
</p>

<p>
mod_log_msgpackではこの部分を利用、アクセスログ1行をMessagePackのarray1個として置き換えて下記の項目のみ保持することとしました。
</p>

(mod_log_msgpack)

<table>
<tr>
<td style="border-top: 1px solid;"><tt>%h</tt></td><td style="border-top: 1px solid;">リモートホスト(を出力する関数をコールバック)</td>
</tr>
<tr>
<td><tt>%l</tt></td><td>(identdからもし提供されていれば)リモートログ名</td>
</tr>
<tr>
<td><tt>%u</tt></td><td>リモートユーザ</td>
</tr>
<tr>
<td><tt>%t</tt></td><td>リクエストを受け付けた時刻</td>
</tr>
<tr>
<td><tt>%r</tt></td><td>リクエストの最初の行</td>
</tr>
<tr>
<td><tt>%&gt;s</tt></td><td>最後のステータス</td>
</tr>
<tr>
<td><tt>%b</tt></td><td>レスポンスのバイト数。HTTPヘッダは除く。</td>
</tr>
<tr>
<td><tt>%{Referer}i</tt></td><td>Referer:ヘッダの内容</td>
</tr>
<tr>
<td><tt>%{User-agent}i</tt></td><td>User-agent:ヘッダの内容</td>
</tr>
</table>

<p>
つまり、用があるのは%?の項目のみということにして、それ以外の固定文字列に関しては無視して
います。%rや%iについていた「"」での囲みも、項目の内容が空白を含みうることを想定して区切
りとしての空白と区別がつかなくなることを回避するためのものなので、arrayとして分割できて
あれば、不要なものとなるわけです。
</p>

<p>
さらに、これらのコールバック関数はrequest_rec構造体(と、%{…}?となったときの{}の中身)を引数にとり、部分文字列を返値とするわけですが、msgpack_packer構造体を渡す引数を1つ追加、ここにログの内容を順次packしていく処理に切り替えています。
</p>

<pre class="prog">
static const char *log_remote_host(request_rec *r, char *a)
{
    return ap_escape_logitem(r-&gt;pool, ap_get_remote_host(r-&gt;connection,
                                                         r-&gt;per_dir_config,
                                                         REMOTE_NAME, NULL));
}
</pre>

<p>
こちらが元々のmod_log_config版。"%h"に対応するコールバックです。mod_log_msgpackになりま
すと下のように変更になりました。
</p>

<pre class="prog">
static int _strpack(const char* s, msgpack_packer* pk)
{
    if (s) {
        size_t n = strlen(s);
        msgpack_pack_raw(pk, n);
        msgpack_pack_raw_body(pk, s, n);
    } else {
        msgpack_pack_nil(pk);
    }
    return 0;
}

static int log_remote_host(request_rec *r, char *a, msgpack_packer* pk)
{
    const char* str = ap_escape_logitem(r-&gt;pool, ap_get_remote_host(r-&gt;connection,
                                        r-&gt;per_dir_config,
                                        REMOTE_NAME, NULL));
    return _strpack(str, pk);
}
</pre>

<p>
log_remot_host()の第3引数が追加され、msgpack_pack_xxxの関数が呼び出されていることが確
認できると思います。
</p>

<p>
あとはここまでログ内容を集めたmsgpack_packer構造体を、ファイルに書き出す関数
apr_file_write()に渡して書き出しを行います。渡す際、mod_log_msgpackであれば行っている部分文字列の連結の箇所がありますが、mod_log_msgpackでは不要なので省略しています。
</p>

<pre class="prog">
static apr_status_t ap_default_log_writer( request_rec *r,
                           void *handle,
                           const char **strs,
                           int *strl,
                           int nelts,
                           apr_size_t len)

{
    char *str;
    char *s;
    int i;
    apr_status_t rv;

#if 0
    // ここから、部分文字列の連結になるので
    str = apr_palloc(r-&gt;pool, len + 1);

    for (i = 0, s = str; i &lt; nelts; ++i) {
        memcpy(s, strs[i], strl[i]);
        s += strl[i];
    }
    // ここまでスキップ。
#else
    str = *strs;
#endif

    rv = apr_file_write((apr_file_t*)handle, str, &amp;len);

    return rv;
}
</pre>

＊＊＊

<p>
おおよその変更の概要は以上です。あとは、mod_log_configとの併存を可能にするためにいくつか細かい変更を加えていますが、次回以降に続くということで^^;。
</p>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51563483" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51500856.html">
<title>Apacheのアクセスログをsyslog経由で出力するためのモジュールを作りました</title>
<link>http://dsas.blog.klab.org/archives/51500856.html</link>
<description>
皆さんは、負荷分散環境でのApacheのアクセスログをどのように取り扱ってますか？


通常、Apacheのログは動作サーバ上のローカルファイルとして出力されるので、
Webサーバを同時に何台も稼働させて負荷分散を行うような環境では、それらすべ
てのWebサーバのログファイル...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-10-22T16:56:19+09:00</dc:date>
<dc:subject>apache</dc:subject>
<content:encoded><![CDATA[<P>
皆さんは、負荷分散環境でのApacheのアクセスログをどのように取り扱ってますか？
</P>
<P>
通常、Apacheのログは動作サーバ上のローカルファイルとして出力されるので、
Webサーバを同時に何台も稼働させて負荷分散を行うような環境では、それらすべ
てのWebサーバのログファイルを集めなければなりません。ローカルファイルとし
て出力されるということは、Webサーバの台数分だけログファイルがばらけること
を意味します。考えるだけでめんどくさいですね。
</P>
<P>
KLabでは、このApacheログを2パターンを使い分けて集めています。ひとつは
syslogによるリモート出力を使い、全Webサーバからのログ出力を一か所に集中さ
せる方法です。これは、CustomLogディレクティブにloggerコマンドを使用するこ
とで可能です。
</P>
<P>
<PRE CLASS="code">

    CustomLog "|/usr/bin/logger -p local6.info --" (書式文字列)

</PRE>
</P>
<P>
これにより、通常ファイル出力されるアクセスログをloggerコマンド経由でsyslog
に渡すことができます。あとはsyslogの設定で、リモートのログ集積サーバに集め
させるというわけです。
</P>
<P>
ただし、これには問題もあります。syslogのログ転送はUDPやバッファリングなど
の関係で取りこぼしがどうしても発生してしまう点です。いくつか対策は考えられ
ますが、私たちはこれに従来型のファイル出力のログを併用することで解決してい
ます。これが2パターンの2つめで、すなわち従来のように各Webサーバ上で出力す
るログファイルを日次バッチで集積するという方法です。詳細なログ解析などはこ
の日次の集積バッチによるログファイルを使用し、その日その日の緊急のアクセス
確認などはsyslog出力の側を見る、という使い分けを行っているのです。
</P>
＊＊＊
<P>
さて、このsyslog出力について、もう一度CustomLogを確認します。loggerコマン
ドへのパイプを用いていますので、httpdの子プロセスとしてloggerプロセスが多
数立ち上がることになります。
</P>
<P>
しかしふと考えてみると、syslogに送るって言ってもやることはsyslog()関数を
呼ぶくらい(他にもopenlog()とかありますが)なので、わざわざ外部プロセスにし
なくても、Apache本体から出力できたっていいよね、と考えたわけです。
</P>
<P>
ということで、Apacheから直接syslogにアクセスログを出力するためのApacheモ
ジュールを一つ作ってみました。
</P>
<PRE>
<DL><DD><LI><A HREF="http://log.blog.klab.org/support/mod_syslog/mod_syslog-0.1.0.tar.gz">mod_syslog-0.1.0.tar.gz</A></DL>
</PRE>
<P>
syslogに送る設定は、以下のようにCustomLogを変更して行います。
</P>
<P>
<PRE class="code">

    CustomLog syslog:foo (書式文字列)

</PRE>
</P>
<P>
"syslog:"をプレフィックスとして付加することで、mod_syslogがsyslogへの出力
であることを判別して処理を行いますが、パイプやファイルパス形式、つまり
"syslog:"が付かない場合は引き続き従来と同じ処理が行われます。
</P>
＊＊＊
<P>
mod_syslogのやることは至ってシンプルです。Apacheは、ログ出力処理のための関
数2つを下に表わすように定義しています。
</P>
<PRE class="code">
  static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle);
  static ap_log_writer* ap_log_set_writer(ap_log_writer *handle);
</PRE>
<P>
ap_log_set_writer_init()は、ログ出力のための初期化処理(ファイルのオープン
など)を行うための関数、またap_log_set_writer()は、実際のログ出力を行う際に
呼ばれる関数をそれぞれコールバック登録します。あとは、Apacheがそれらのコー
ルバック関数を必要なタイミングで呼び出してくれます。
</P>
<P>
さらに上記の関数2つは返値を持ち、それぞれのコールバック関数の事前の値を表し
ます。mod_syslogは"syslog:"のプレフィックス以外のログ出力先、すなわちパイプ
やファイル出力については従来の処理に任せますので、mod_syslog自身のコールバッ
ク関数登録と同時に従来のコールバック関数へのポインタを、この返値によって取得、保持します。
</P>
<PRE class="code">
#define PREFIX_SYSLOG   "syslog:"
#define PREFIX_SYSLOG_LENGTH    7

static void *
ap_syslog_writer_init(apr_pool_t *p, server_rec *s,
                      const char* name)
{
    syslog(LOG_DEBUG, "%s: prev_log_writer_init = %p, name = %s", __func__, prev_log_writer_init, name);

    if (strncasecmp(PREFIX_SYSLOG, name, PREFIX_SYSLOG_LENGTH) == 0) {
        return &dummy[0];
        // NULL以外を返す。
        // 同じ値(&dummy[0])かどうかをap_syslog_writer()関数で判別できればよい。
    }

    if (prev_log_writer_init) {
        return prev_log_writer_init(p, s, name);
    }

    return NULL;
}

// ap_hook_pre_config()でフック登録
static int
syslog_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
{
    ...

    if (!prev_log_writer_init) {
        void* f;

        f = ap_log_set_writer_init(ap_syslog_writer_init);
        if (f != ap_syslog_writer_init) {
            prev_log_writer_init = f;
        }
        f = ap_log_set_writer(ap_syslog_writer); // ap_syslog_writerの内容については省略
        if (f != ap_syslog_writer) {
            prev_log_writer = f;
        }
    }

    return OK;
}
</PRE>
<P>
つまり、上記の例で言えばprev_log_writer_initとprev_log_writerに従来の処理
へのコールバック関数のポインタが入るわけです。

なお、この2関数が返値を返すようになったのはApache2.2以降なので、Apache2.0
系ではそのままでは使用できません。一応、同名の関数から旧い値を返させるだけ
で動作するところまでは確認していますが、もしお試しの際はご注意ください。
</P>
＊＊＊
<P>
このように、Apacheからアクセスログを出力するにあたり、モジュールの追加だけ
でも結構な機能追加ができることが分かります。しかも、添付の例をご覧のように、
わずかなコード量で実現できています。あったらいいな、こんなことできたらうれ
しいな、というちょっとした発想を柔軟に取り入れられるApacheの仕組みにはやは
り目を見張るものがありますね。
</P>

<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51500856" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51494587.html">
<title>Windows用ソフトウェア「イージスガード」を公開します</title>
<link>http://dsas.blog.klab.org/archives/51494587.html</link>
<description>
「イージスガード」は Windows PC 上のデータをウイルスやマルウェアの脅威から守るためのソフトウェアです。KLab は個人向けにこのソフトウェアの無償公開を開始しました。




ダウンロードはこちらから

イージスガード公式ページ（KLab サイトへ）





イージスガード...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-10-05T22:22:24+09:00</dc:date>
<dc:subject>win</dc:subject>
<content:encoded><![CDATA[<p>
「イージスガード」は Windows PC 上のデータをウイルスやマルウェアの脅威から守るためのソフトウェアです。KLab は個人向けにこのソフトウェアの無償公開を開始しました。
<p>
<center>
<a href="http://www.klab.jp/ag/aegisguard/"><img src="http://image.blog.livedoor.jp/klab_gijutsu2/imgs/4/2/420264a2.png" alt="イージスガード"  border=0></a>
<br>
ダウンロードはこちらから
<br>
<a href="http://www.klab.jp/ag/aegisguard/"><b>イージスガード公式ページ（KLab サイトへ）</b></a>
</center>

<p>
<hr size=1>
<p>
イージスガードには次の機能・特長があります。

<ul>
<li>所定のフォルダ・ファイルを保護対象として設定可能
<li>許可しないプログラムからのアクセスを報告・記録する
<li>許可しないプログラムからのアクセスを透過的にダミーフォルダへ誘導
<li>PC 環境に応じて保護設定を自動生成する
<li>改変されたプログラムからのアクセスを抑制する
<li>有効なデジタル署名つきのプログラムには自動的に許可を与える
</ul>

<p>
イージスガードは、以前このブログでご紹介した「WinAmulet」を母体とする上位互換のソフトウェアです。WinAmulet ユーザ各位のご支援のおかげで、多くの機能を追加し大きく性能を改善したこの新しいソフトウェアが生まれました。もちろん、WinAmulet の保護設定をインポートすることも可能です。
<p>
イージスガードに使用制限はありません。多くの方に自由にご利用頂くことで、悲惨な情報流出被害発生の防止につながれば、と願っています。
<hr>
(tanabe)
<br clear="all">
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51494587" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51491918.html">
<title>Bazaar 2.0 がリリースされました</title>
<link>http://dsas.blog.klab.org/archives/51491918.html</link>
<description>
過去に Bazaarの紹介 で紹介したときには 1.9 だったBazaarですが、その後も毎月のリリースをかさねて先週とうとう メジャーバージョンアップとなる 2.0 がリリースされました。(ダウンロードサイト) 


正式なリリースノートは公式Webサイトを参照してもらうとして、この一...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-09-28T21:14:37+09:00</dc:date>
<dc:subject>Python</dc:subject>
<content:encoded><![CDATA[<p>
過去に <a href="http://dsas.blog.klab.org/archives/51344422.html">Bazaarの紹介</a> で紹介したときには 1.9 だったBazaarですが、その後も毎月のリリースをかさねて先週とうとう メジャーバージョンアップとなる 2.0 がリリースされました。(<a href="http://bazaar-vcs.org/Download">ダウンロードサイト</a>) 
</p>
<p>
正式なリリースノートは公式Webサイトを参照してもらうとして、この一年弱で改良された点を私の基準で紹介したいと思います。
</p>


<h3>TortoiseBZRが(たぶん)実用レベルになった</h3>
<p>
私はたいていコマンドラインから利用しているので、以前紹介したときはTortoiseBZRをあまり使い込んでいませんでした。
</p>
<p>
その後、TortoiseBZRを使い込んでみたところ、pushができない、addもできないなど最低限の機能がそろっていなかったり、ステータスの表示が重くてストレスになったりしたので結局アンインストールしてしまいました。
</p>
<p>
その後今年に入ってからTortoiseBZRの開発が停滞してしまい、このままじゃいけないと思って6月後半からTortoiseBZRの開発に参加しました。この2ヶ月で以下のような問題を解決しました。
</p>

<ul>
    <li>シェル拡張の致命的なバグ(「新しいフォルダを作成」などのボタンが動作しなくなる、Windows Vistaでコンテキストメニューのレイアウトが崩れるなど)が修正されました。</li>
    <li>ステータスの取得が速くなりました。また、まだステータスを取得していないファイルの場合 '?' マークのステータスアイコンを表示してバックグラウンドでステータスを取得することで、エクスプローラの応答速度の低下を抑えました。(この方法はTortoiseHGの開発者にTwitterで教えてもらって開発しました。感謝感謝)</li>
    <li>add, push, send といった機能をコンテキストメニューに追加しました。</li>
</ul>

<p>
まだTortoiseSVNの完成度には到達していませんが、とりあえずユーザーを邪魔をする挙動が無くなって基本的な操作の大半がコンテキストメニューから呼び出せるようになったので、人に試してみてと言える状態になっています。
</p>

<h3>
新しいリポジトリフォーマットが標準になった
</h3>

<p>
Bazaar 2.0 からは 2a といわれる新らしいリポジトリフォーマットが標準になりました。
Bazaarではデータの格納方式が変わる以外にも、新機能のために新しいメタデータを追加した時にも古いバージョンのBazaarからそのメタデータがないリビジョンをコミットされてしまわないようにとリポジトリフォーマットを変更しています。その結果としてBazaarには大量のリポジトリフォーマットができてしまい、「○○のフォーマットでは△△の機能が使えない」といった問題が発生していました。
</p>

<p>
新しいフォーマットが標準になることで、リポジトリフォーマットをオプションから選ばなくても新しい機能が全部使える、リポジトリサイズが小さくなったりいくつかの操作が速くなっていたりするという利点があります。
</p>


<h3>
WindowsでのUnicodeファイル名への対応が改良された
</h3>

<p>
PythonではUnicode APIを利用することで、Unicodeファイル名でファイルを扱うことができるのですが、 sys.argv で取れるコマンドライン引数は非Unicodeです。(Python3ではUnicodeになります)
Bazaarも sys.argv を利用していたため、せっかくUnicodeでファイル名を扱うのにコマンドライン引数からはコードページでしかファイル名を取得できないという問題がありました。
</p>
<p>
最近のバージョンではこの部分が GetCommandlineW() APIを利用するようになり、bzr本体だけでなくQBzr等のGUIを含めてUnicodeへの対応が進んでいるので、Unicodeファイル名に関する問題はほとんどなくなりました。
</p>


<h3>
日本語ユーザーグループができた
</h3>

<p>
日本語で議論ができる環境が欲しいと思い、Bazaar 2.0 のリリースをきっかけにユーザーグループを作ることにしました。 <a href="http://groups.google.co.jp/group/bazaar-ja">http://groups.google.co.jp/group/bazaar-ja</a>
</p>

<p>
Launchpad上にドキュメント翻訳プロジェクトも作成し、ゆっくりですが翻訳作業も開始しています。TortoiseBZRのバグ報告や要望なんかも、英語でLaunchpadに登録するよりも手軽にできるはずです。Bazaarに関心のある方はぜひ参加してみてください。
</p>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51491918" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51483496.html">
<title>KLab勉強会#5の資料公開</title>
<link>http://dsas.blog.klab.org/archives/51483496.html</link>
<description>
8/31 に開催した、第5回KLab勉強会の資料を公開します。



  『Gainerでアイデアをフィジカルにスケッチする』
    
    &amp;nbsp;&amp;nbsp;～ Gainerでアイデアをフィジカルにスケッチする
  
    
      発表資料 (PDF, 5.5 MB)
      
    
 


  『おしゃべりコーヒーボット...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-09-09T19:00:02+09:00</dc:date>
<dc:subject>KLab勉強会</dc:subject>
<content:encoded><![CDATA[<p>
8/31 に開催した、<a href="http://dsas.blog.klab.org/archives/51466043.html">第5回KLab勉強会</a>の資料を公開します。
</p>

<dl>
  <dt>『Gainerでアイデアをフィジカルにスケッチする』
    <br>
    &nbsp;&nbsp;～ Gainerでアイデアをフィジカルにスケッチする
  <dd>
    <ul>
      <li><a href="http://lab.klab.org/files/klab_study/5/klab5-takei-gainer.pdf">発表資料</a> (PDF, 5.5 MB)
      </li>
    </ul>
 </dl>

<dl>
  <dt>『おしゃべりコーヒーボット』
    <br>
    &nbsp;&nbsp;～ 宇夫 陽次朗 (株式会社IIJイノベーションインスティチュート) 
  <dd>
    <ul>
      <li><a href="http://lab.klab.org/files/klab_study/5/klab5-yuo-coffeebot.pdf">発表資料</a> (PDF, 2.1 MB)
      </li>
    </ul>
  </dl>

<dl>
  <dt>『hwhack: USB解析のいろいろ』
    <br>
    &nbsp;&nbsp;～ 宇夫 陽次朗 (株式会社IIJイノベーションインスティチュート) 
  <dd>
    <ul>
      <li><a href="http://lab.klab.org/files/klab_study/5/klab5-yuo-usb.pdf">発表資料</a> (PDF, 6.8 MB)
      </li>
    </ul>
  </dl>

<dl>
  <dt>『3DCADやRPによるハードウェア開発』
    <br>
    &nbsp;&nbsp;～ 松村 礼央(株式会社国際電気通信基礎技術研究所（ATR）知能ロボティクス研究所（IRC）環境知能研究室 研修研究員) 
  <dd>
    <ul>
      <li><a href="http://lab.klab.org/files/klab_study/5/klab5-matsumura-robot.pdf">発表資料</a> (PDF, 849 KB)
      </li>
    </ul>
  </dl>

<p>
先日の勉強会はちょうど台風の最中でしたが、お越しいただいたきありがとうございました。<br>
みなさんのおかげで懇親会も楽しく過すことができました。<br><br>
勉強会の様子は、動画のほうを準備していますので今暫くお待ちください。
</p>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51483496" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51472145.html">
<title>「WinAmulet」バージョンアップのお知らせ(2009/08/13)</title>
<link>http://dsas.blog.klab.org/archives/51472145.html</link>
<description>Windows 用フリーソフトウェア「WinAmulet」をバージョンアップしました。
新しいバージョンは「0.9.4.0」です。




旧バージョンをご利用中の方も、初めての方も、ぜひ最新の WinAmulet をお試し下さい。

WinAmulet のページ

・ダウンロードはこちらから

・...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-08-13T13:58:06+09:00</dc:date>
<dc:subject>win</dc:subject>
<content:encoded><![CDATA[Windows 用フリーソフトウェア「<a href="http://dsas.blog.klab.org/archives/51301907.html">WinAmulet</a>」をバージョンアップしました。<br>
新しいバージョンは「0.9.4.0」です。

<p>
<img src="http://image.blog.livedoor.jp/klab_gijutsu2/imgs/a/b/ab9b7bf1.png" alt="WinAmulet0.9.4.0">

旧バージョンをご利用中の方も、初めての方も、ぜひ最新の WinAmulet をお試し下さい。
</p><center>
<a href="http://dsas.blog.klab.org/archives/51301907.html"><font size=+1><b>WinAmulet のページ</b></font></a>
<br>
・<a href="http://dsas.blog.klab.org/archives/51301907.html#platforms">ダウンロードはこちらから</a>
<br>
・<a href="http://dsas.blog.klab.org/archives/51301907.html#oops">重要なお知らせ！</a>
</center>

<p>
<b>■ このプログラムの概要</b>

</p><p>
「WinAmulet」は、所定のフォルダに対しアクセス可能なプログラムを制限するソフトウェアです。対象フォルダ下の大切なファイルにユーザの許可しないプログラムがアクセスすることを防ぎます。

</p><p>
<b>■ 主な更新内容</b>
</p>
バージョン 0.9.3.0 -&gt; 0.9.4.0 での主な更新内容は以下の通りです。
<br>
<ul>
<li>キャッシュ機構の実装により処理効率を改善しました 
</li><li>リダイレクト処理の精度を改善しました
</li><li>ファイルオープン要求中の各プロセス名を確認できるようにしました
</li></ul>
<hr>
(tanabe)
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51472145" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51466043.html">
<title>KLab勉強会#5開催のお知らせ</title>
<link>http://dsas.blog.klab.org/archives/51466043.html</link>
<description>
第5回KLab勉強会のお知らせです。
今迄のテーマはネットワークに関わることをメインにKLab勉強会を開催してき
ましたが、今回は少し趣向を変えハードウェアについて扱っていきます。


ハードウェアと一口にいっても様々な分野があります。
今回は外部から宇夫陽次朗氏(株式...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-07-31T16:17:05+09:00</dc:date>
<dc:subject>KLab勉強会</dc:subject>
<content:encoded><![CDATA[<P>
第5回KLab勉強会のお知らせです。<BR>
今迄のテーマはネットワークに関わることをメインにKLab勉強会を開催してき
ましたが、今回は少し趣向を変えハードウェアについて扱っていきます。
</P>
<P>
ハードウェアと一口にいっても様々な分野があります。
今回は外部から宇夫陽次朗氏(株式会社IIJイノベーションインスティチュート)
と松村礼央氏(株式会社国際電気通信基礎技術研究所)をお招きする予定です。
</P>
<P>
　宇夫氏からはUSBデバイスの解析方法について、また松村氏からは近い将来
身近な存在になるロボットの開発についてお話を頂きます。
</P>
<P>
併せて弊社から、USBデバイスを経由し手軽に工作ができるGainer(ゲイナー)の導入編から事例も交えお話しさせていただきます。
</P
<P>
いずれかのセッションでも興味のあるかたお待ちしております!
</P>

<H3>開催要項</H3>

<DL>
<DT>日時
<DD>2009/8/31 (月) 19:00-21:10 (18:30受付開始)
<DT>場所
<DD>KLab株式会社 第3会議室<BR>
    東京都港区六本木6-10-1 六本木ヒルズ森タワー20F<BR>
    (<a href="http://www.klab.org/comp/access.html">アクセス方法</a>)
<DT>参加費
<DD>無料
<DT>人数
<DD>30名程度<BR>
    (定員になり次第、参加登録を締め切らせていただきます。)
</DL>
<P>
※終了後に懇親会(会費制)を予定しています。
</P>

<H3>セッション</H3>
<OL>
<LI>
<DL>
<DT>タイトル
<DD>『Gainerでアイデアをフィジカルにスケッチする』
<DT>講師
<DD>竹井 英行(KLab株式会社)
<DT>概要
<DD>
<P>
フィジカル・コンピューティングのための入門的なツールキットGainer(ゲイナー)を使って、LEDやアクチュエータなどのハードウェアを簡単なプログラムで動かす方法を説明する。またその中で、Gainerを使いこなすために必要な電気回路の基礎も説明する。その後、応用として、Zigbee+Gainerによるデモンストレーションを
紹介する。
</P>
</DL>
</LI>
<LI>
<DL>
<DT>タイトル
<DD>『hwhack: USB解析とかいろいろ』
<DT>講師
<DD>宇夫 陽次朗 (株式会社IIJイノベーションインスティチュート)
<DT>概要
<DD>
<P>
　コンピュータと周辺機器をつなげるためのインターフェイスとしてUSBが広く普及した。PCから組み込み機器といったホスト側や、様々な周辺機器群がUSBインターフェイスを装備し、多くのOSはUSBサポートの機能を標準的に提供している。<BR>
　今回はUSBの概略を説明し、USBデバイスの挙動を解析する手法を紹介する。またBSD系OSでのデバイスドライバとの関係も扱っていきたい。
</P>
</DL>
</LI>
<LI>
<DL>
<DT>タイトル
<DD>『3DCADやRPによるハードウェア開発』
<DT>講師
<DD>松村 礼央(株式会社国際電気通信基礎技術研究所（ATR）知能ロボティクス研究所（IRC）環境知能研究室 研修研究員)
<DT>概要
<DD>
<P>
　近年、フィジカルコンピューティングをはじめ、インタラクティブな製品の開発が盛んに行われています。そこで今回は，人とコミュニケーションをとるロボットの開発を例に 3DCADやラピッド・プロトタイピング（RP）によるハードウェアの開発方法について概説します。
</P>
</DL>
</LI>
</OL>
<H3>参加方法</H3>
<P>
<a href="mailto:register-study-20090831@klab.jp">register-study-20090831@klab.jp</a> 宛に件名を「参加登録」として、以下の内容のメールを送ってください。<BR>
</P>
<pre class="code">
氏名　　　　：
所属　　　　：（会社名・学校名等）
懇親会　　　：（参加する・しない）
URL 　　　　：ご自身のブログなどがあればそのURLを。（任意）
コメント　　：勉強会についての希望や参加の意気込みなど、
　　　　　　　なんでも結構ですので、よろしければ一言コメ
　　　　　　　ントいただけるとうれしいです。（任意）
</pre>

<P>
※当日は、受付にて名刺を一枚頂戴いたしますので、予めご用意下さい。
</P>

<hr>

<div style="background: #FFFABF; border: #EF720E 2px dotted;padding-left:1em;padding-right:1em;">
<p>
申し込みを終了致しました。ご応募ありがとうございました。
<br>

参加希望のメールをいただいた方には、順次、当日のご案内をメールでお送り致します。
<br>

万一、参加登録後に都合が悪くなってしまった場合は、当日でもかまいませんので<a href="mailto:register-study-20090831@klab.jp">register-study-20090831@klab.jp</a>までご連絡いただけると助かります。
</p>
<p>
また、申し込み終了後に参加希望のメールをいただいた方には、定員超過の旨、メールでご連絡いたします。今回は参加いただけませんが、次回の参加をお待ちしております。
</p>
</div>


</p>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51466043" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51456004.html">
<title>MessagePackのPython Bindingをリリースしました</title>
<link>http://dsas.blog.klab.org/archives/51456004.html</link>
<description>MessagePack とは、古橋(id:viver)さんが開発された高速・高効率なバイナリシリアライズフォーマットです。詳しくは 古橋さんの日記 やプロジェクトサイト を見てください。
PythonからMessagePackフォーマットでSerialize/DeserializeするためのPythonパッケージを作ったの...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-07-13T15:58:21+09:00</dc:date>
<dc:subject>Python</dc:subject>
<content:encoded><![CDATA[<p>MessagePack とは、古橋(id:viver)さんが開発された高速・高効率なバイナリシリアライズフォーマットです。詳しくは <a class="reference external" href="http://d.hatena.ne.jp/viver/20080816/p1">古橋さんの日記</a> や<a class="reference external" href="http://msgpack.sourceforge.jp/">プロジェクトサイト</a> を見てください。</p>
<p>PythonからMessagePackフォーマットでSerialize/DeserializeするためのPythonパッケージを作ったので、取得方法と使い方について簡単に紹介します。</p>
<div class="section" id="id3">
<h3>1. インストール</h3>
<p>msgpackという名前でPython Package Index (PyPI)に登録してあります。 <a href="http://pypi.python.org/pypi/msgpack/">&lt;http://pypi.python.org/pypi/msgpack/&gt;</a></p>
<p>setuptoolsをインストールしている環境では、</p>
<pre class="terminal">
$ easy_install msgpack
</pre>
<p>でインストールすることができます。</p>
<p>Windowsでインストールする場合は、<a href="http://pypi.python.org/pypi/msgpack/">PyPIのパッケージサイト</a> からインストーラをダウンロードしてインストールするのがお手軽です。</p>
</div>
<div class="section" id="id4">
<h3>2. シリアライズ</h3>
<p>まず、msgpackパッケージをimportします。</p>
<pre class="prog">
&gt;&gt;&gt; import msgpack
&gt;&gt;&gt; help(msgpack)  # docstring を読む
</pre>
<p>一つのオブジェクトをシリアライズするには、 <tt class="docutils literal"><span class="pre">msgpack.packb()</span></tt> を利用するのが簡単です。</p>
<pre class="prog">
&gt;&gt;&gt; msgpack.packb([1,2,3])
'\x93\x01\x02\x03'
</pre>
<p>連続してシリアライズする場合、 <tt class="docutils literal"><span class="pre">msgpack.Packer</span></tt> オブジェクトを利用するとオーバーヘッドが少なくなります。</p>
<pre class="prog">
&gt;&gt;&gt; packer = msgpack.Packer()
&gt;&gt;&gt; packer.pack([1,2,3])
'\x93\x01\x02\x03'
&gt;&gt;&gt; packer.pack([4,5,6])
'\x93\x04\x05\x06'
</pre>
</div>
<div class="section" id="id5">
<h3>3. デシリアライズ</h3>
<p><tt class="docutils literal"><span class="pre">msgpack.unpackb()</span></tt> を利用すると、１オブジェクト分のシリアライズされたデータをデシリアライズできます。</p>
<pre class="prog">
&gt;&gt;&gt; msgpack.unpackb(b'\x93\x01\x02\x03')
[1, 2, 3]
</pre>
<p>ストリームからデシリアライズする場合、 <tt class="docutils literal"><span class="pre">msgpack.Unpacker</span></tt> オブジェクトを利用することで、連続したデシリアライズができたり、オブジェクトの境界が判らない場合に対応できます。</p>
<pre class="prog">
&gt;&gt;&gt; unpacker = msgpack.Unpacker()
&gt;&gt;&gt; buf = b'\x93\x01\x02\x03' * 5
&gt;&gt;&gt; len(buf)
20
&gt;&gt;&gt; unpacker.feed(buf[:9])
&gt;&gt;&gt; for o in unpacker:
...     print o
...
[1, 2, 3]
[1, 2, 3]
&gt;&gt;&gt; unpacker.feed(buf[9:])
&gt;&gt;&gt; for o in unpacker:
...     print o
...
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
</pre>
</div>
<div class="section" id="id6">
<h3>4. ベンチマーク</h3>
<p>テストコード:</p>
<pre class="prog">
#!/usr/bin/env python
# coding: utf-8

from msgpack import packs, unpacks
from cPickle import dumps, loads
import simplejson as json
from time import time

BENCH_NUM = 10

def bench(func, num=BENCH_NUM):
    start = time()
    for i in xrange(BENCH_NUM):
            func()
    end = time()
    print &quot;%-12s  %4.3f[ms]&quot; % (func.__name__, (end-start)*1000/BENCH_NUM)

def setup_int():
    global a, a_pickle, a_mpack, a_json
    a = range(1024) * 2**10
    a_pickle = dumps(a)
    a_json = json.dumps(a)
    a_mpack = packs(a)

def setup_str():
    global a, a_pickle, a_mpack, a_json
    a = ['a'*(i % 4096) for i in xrange(2**14)]
    a_pickle = dumps(a)
    a_json = json.dumps(a)
    a_mpack = packs(a)


def pickle_dump(): dumps(a)
def pickle_load(): loads(a_pickle)

def json_dump(): json.dumps(a)
def json_load(): json.loads(a_json)

def mpack_pack(): packs(a)
def mpack_unpack(): unpacks(a_mpack)


targets = [
        pickle_dump, pickle_load,
        json_dump, json_load,
        mpack_pack, mpack_unpack]
import gc
gc.disable()

bytes_suffix = &quot;[bytes]&quot;

print &quot;== Integer ==&quot;
setup_int()

print &quot;= Size =&quot;
print &quot;pickle:&quot;, len(a_pickle), bytes_suffix
print &quot;json:  &quot;, len(a_json), bytes_suffix
print &quot;mpack: &quot;, len(a_mpack), bytes_suffix

for t in targets:
    bench(t)

print &quot;== String ==&quot;
setup_str()

print &quot;= Size =&quot;
print &quot;pickle:&quot;, len(a_pickle), bytes_suffix
print &quot;json:  &quot;, len(a_json), bytes_suffix
print &quot;mpack: &quot;, len(a_mpack), bytes_suffix

for t in targets:
    bench(t)
</pre>
<p>結果:</p>
<pre class="terminal">
== Integer ==
= Size =
pickle: 6203398 [bytes]
json:   5154816 [bytes]
mpack:  2752517 [bytes]
pickle_dump   248.640[ms]
pickle_load   360.288[ms]
json_dump     255.601[ms]
json_load     136.922[ms]
mpack_pack    51.383[ms]
mpack_unpack  26.851[ms]
== String ==
= Size =
pickle: 33731696 [bytes]
json:   33611776 [bytes]
mpack:  33595139 [bytes]
pickle_dump   182.324[ms]
pickle_load   141.639[ms]
json_dump     126.675[ms]
json_load     93.945[ms]
mpack_pack    66.833[ms]
mpack_unpack  34.953[ms]
</pre>
<p>pickleやjsonを圧倒していますが、まだまだ改善の余地がありそうです。
とくにpackはunpackと違って大量のPythonオブジェクトを生成する必要があるわけではないのに、unpackよりも時間がかかってしまっています。</p>
</div>
<div class="section" id="id7">
<h3>5. その他</h3>
<p>ここでは紹介していない、simplejsonやpickleモジュールに似せたAPIもあります。pickleやjsonからmsgpackへ移行するときはパッケージの中を探してみて下さい。</p>
<p>ただし、現在のmsgpackはバイト列・整数・浮動小数点数・シーケンス型・辞書型にしか対応できていません。simplejsonは <tt class="docutils literal"><span class="pre">dumps()</span></tt> に <tt class="docutils literal"><span class="pre">defalut()</span></tt> 関数を、
<tt class="docutils literal"><span class="pre">loads()</span></tt> に <tt class="docutils literal"><span class="pre">object_hook()</span></tt> 関数を用意することでユーザーが定義したクラスのシリアライズ・デシリアライズができます。0.2 では同じような <tt class="docutils literal"><span class="pre">default()</span></tt> と<tt class="docutils literal"><span class="pre">object_hook()</span></tt> へ対応しようと思います。</p>
</div>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51456004" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51434186.html">
<title>Windowsプログラムの異常終了をトラップするコード</title>
<link>http://dsas.blog.klab.org/archives/51434186.html</link>
<description>■ はじめに


先日、社内でこういう話題がありました。

「Windows 上のプログラム A からソースコードのないプログラム B を起動する必要があるんだけど、プログラム B はときどき異常終了しちゃったりする。内輪用だから落ちること自体は目をつぶるとして、プログラ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-06-24T10:59:44+09:00</dc:date>
<dc:subject>win</dc:subject>
<content:encoded><![CDATA[<b>■ はじめに</b>
<br>
<br>
先日、社内でこういう話題がありました。
<br>
「Windows 上のプログラム A からソースコードのないプログラム B を起動する必要があるんだけど、プログラム B はときどき異常終了しちゃったりする。内輪用だから落ちること自体は目をつぶるとして、プログラム B が異常終了した場合にはプログラム A 側でそれを上手にハンドルしたい。良い方法はないものか」
<br><br>
この話に興味を感じ、異常終了を起こす短いプログラムを作ってデバッガでトレースしながらヒントを探している内にふと思いました。
<br><br>
<center>
<img src="http://image.blog.livedoor.jp/klab_gijutsu2/imgs/4/b/4b029333.png">
</center>
<br>
このプログラムを裸で実行すると、プログラム内で処理されない例外は図のような形でシステムによって処理されます。しかし、デバッガ上でデバッギ（デバッグ対象）として実行している場合はデバッガが例外の発生を検知しそれをユーザに伝えます。つまり、デバッガの制御下にあります。
<br><br>
ということは「デバッガとして動作するコード」を用意しプログラム B をデバッギとして扱えば、そこで発生した未処理の例外を捕捉することができるかもしれません。

ちょっと面白そうなので試しにそういうプログラムを書いてみることにしました。
<a href="http://dsas.blog.klab.org/archives/51434186.html">続きを読む</a>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51434186" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51423317.html">
<title>まくおさんバージョンアップのお知らせ(Ver1.2.0)</title>
<link>http://dsas.blog.klab.org/archives/51423317.html</link>
<description>
まくおさんをバージョンアップしましたのでお知らせします。
主な変更点は以下のとおりです。


【Ver1.1.3→Ver1.2.0】

応答速度と安定性の向上
エラーログに&quot;[error]&quot;という文字列を追加
メンバがタイムアウトしたときの状況を詳細に出力するようにした
msync ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-05-25T21:23:07+09:00</dc:date>
<dc:subject>運用</dc:subject>
<content:encoded><![CDATA[<P>
まくおさんをバージョンアップしましたのでお知らせします。<BR>
主な変更点は以下のとおりです。
</P>
<P>
【Ver1.1.3→Ver1.2.0】
<UL>
<LI>応答速度と安定性の向上
<LI>エラーログに"[error]"という文字列を追加
<LI>メンバがタイムアウトしたときの状況を詳細に出力するようにした
<LI>msync --statusで、実行中のコマンドを表示するようにした
<LI>msyncを複数同時実行したときに挙動がおかしくなる不具合を修正
<LI>ファイルクローズに失敗したときに異常終了する不具合を修正
<LI>msyncにdeleteオプションを指定したときの結果表示がおかしくなる不具合を修正
<LI>その他細かい不具合を修正
</UL>
</P>
<P>
【ダウンロード】
<UL>
<LI><B><A HREF="http://sourceforge.net/project/showfiles.php?group_id=241125">ダウンロードページ</A></B>
<LI><B><A HREF="http://downloads.sourceforge.net/makuosan/makuosan-1.2.0.tar.gz">makuosan-1.2.0.tar.gz</A></B>
</UL>
</P>
<FONT COLOR=RED><B>
【注意】<BR>
Ver1.2系とVer1.1系はプロトコルに互換性がありませんので、<BR>
バージョンアップは全サーバに対して実施して下さい。<BR>
</B></FONT>
</P>
<P>
「ところで、まくおさんってだれ？」という方は、<A HREF="http://lab.klab.org/wiki/Makuosan">こちら</A>や<A HREF="http://dsas.blog.klab.org/archives/51342234.html">こちら</A>を見てやってください(^^;
</P>

<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51423317" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51395944.html">
<title>phpを高速化する computed goto</title>
<link>http://dsas.blog.klab.org/archives/51395944.html</link>
<description>前回 インタプリタ型言語を高速化する computed goto で紹介したcomputed gotoを、「phpでも使えないの？」という声が社内であったので、 php のソースコードを見たところ、特定のビルド手順で php でも computed goto が使えることが判りました。そのビルド手法とベンチマー...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-03-30T16:03:46+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<p>前回 <a class="reference" href="http://dsas.blog.klab.org/archives/51393628.html">インタプリタ型言語を高速化する computed goto</a> で紹介したcomputed gotoを、「phpでも使えないの？」という声が社内であったので、 php のソースコードを見たところ、特定のビルド手順で php でも computed goto が使えることが判りました。そのビルド手法とベンチマーク結果を紹介しておきます。</p>
<p>php の VM のソースコードは、phpソースパッケージ中の Zend/ というディレクトリの中にあります。zend_vm_で始まる幾つかのファイルのうち、 zend_vm_execute.h というファイルが命令ディスパッチが実装されているファイルで、このファイルは zend_vm_gen.php というスクリプトで生成されています。そして、 zend_vm_gen.php のオプションで、命令ディスパッチの方法を選択できます。(phpのビルドにphpが必要です)</p>
<p>computed goto を使うビルド手順は以下の通りになります。</p>
<pre class="terminal">
$ tar xzf php-5.2.x
$ cd xzf php-5.2.x/Zend
$ php zend_vm_gen.php --with-vm-kind=GOTO
$ cd ..
$ ./configure --with-zend-vm=GOTO [その他オプション]
$ make
</pre>
<p>Zend/ ディレクトリの中に bench.php というファイルがあったので、これを使って通常の関数ポインタ配列版とcomputed goto版の速度を比較してみました。</p>
<pre class="terminal">
# 関数ポインタ配列版.
$ ~/local/stow/php-5.2.9-func/bin/php bench.php
simple             0.319
simplecall         0.412
simpleucall        0.639
simpleudcall       0.693
mandel             0.991
mandel2            1.311
ackermann(7)       0.767
ary(50000)         0.047
ary2(50000)        0.037
ary3(2000)         0.534
fibo(30)           1.739
hash1(50000)       0.087
hash2(500)         0.098
heapsort(20000)    0.312
matrix(20)         0.257
nestedloop(12)     0.539
sieve(30)          0.232
strcat(200000)     0.034
------------------------
Total              9.047

# computed goto版
$ ~/local/stow/php-5.2.9-goto/bin/php bench.php
simple             0.283
simplecall         0.360
simpleucall        0.584
simpleudcall       0.645
mandel             1.022
mandel2            1.213
ackermann(7)       0.788
ary(50000)         0.046
ary2(50000)        0.036
ary3(2000)         0.485
fibo(30)           1.716
hash1(50000)       0.079
hash2(500)         0.090
heapsort(20000)    0.276
matrix(20)         0.237
nestedloop(12)     0.479
sieve(30)          0.234
strcat(200000)     0.035
------------------------
Total              8.610
</pre>
<p>5%くらい速くなっていますね。
Python 3.1 だけじゃなくて php をビルドするときも computed goto を試してみて下さい。</p>

<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51395944" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51393628.html">
<title>インタプリタ型言語を高速化する computed goto</title>
<link>http://dsas.blog.klab.org/archives/51393628.html</link>
<description>先日Python 3.1a1 がリリースされました。 Python 3.0 は Python 2.6 に比べてパフォーマンスが悪かったのですが、Python3.1はPython2.6よりも速くなるかもしれません。
Python3.1のパフォーマンス向上は、主に次の2点が影響しています。

ioモジュールがC言語で書き直さ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-03-23T16:04:37+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<p>先日Python 3.1a1 がリリースされました。 Python 3.0 は Python 2.6 に比べてパフォーマンスが悪かったのですが、Python3.1はPython2.6よりも速くなるかもしれません。</p>
<p>Python3.1のパフォーマンス向上は、主に次の2点が影響しています。</p>
<ul>
<li>ioモジュールがC言語で書き直された</li>
<li>computed goto の採用 (--with-computed-gotos というconfigureオプションで有効)</li>
</ul>
<p>computed goto という名前を聞き慣れなかったのですが、調べてみると  Ruby 1.9 の VM (YARV) や、 Perl6 の VM として開発されとうとうリリースされた Parrot にも採用されている手法でした。今回は簡単に computed goto の紹介をしてみます。</p>
<div class="section">
<h3><a id="label-as-value" name="label-as-value">とりあえず label as value</a></h3>
<p>C言語の規格で規定されているgoto文は、ラベルに対して無条件ジャンプする構文です。このようにして使います。</p>
<pre class="prog">
    goto label;
    puts(&quot;foo&quot;); // 表示されない.
label: //ここにジャンプする.
    puts(&quot;bar&quot;);
</pre>
<p>ラベルはシンボル（名前）であって値ではないのですが、ラベルのアドレスを取得する <a class="reference" href="http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html">label as value</a> という拡張機能がgccにあります。</p>
<p>label as value を使うと、上記のコードは次のように書くことが出来ます。</p>
<pre class="prog">
    void *jump_target = &amp;&amp;label;
    goto *jump_target;
    puts(&quot;foo&quot;);
label:
    puts(&quot;bar&quot;);
</pre>
<p>ジャンプ先アドレスを変数に格納できるのがキモになっています。</p>
</div>
<div class="section">
<h3><a id="computed-goto-switch" name="computed-goto-switch">computed goto を使ってswitch文を高速化</a></h3>
<p>インタプリタ型言語では大抵、次のようなバイトコードに対応した処理を実行する部分(命令ディスパッチ)が実行時間の大半を占めます。</p>
<pre class="prog">
for (;;) {
    code = *code_pc++;
    switch (code) {
    case CODE_ADD:
        // 足し算処理.
        break;
    case CODE_SUB:
        // 引き算処理.
        break;
    // ...
    case CODE_END:
        goto LOOP_END;
    }
}
LOOP_END;
</pre>
<p>上記の実装では、バイトコードを1命令処理するのに次の2つの分岐を実行しなければなりません。</p>
<ul>
<li>switch-case による処理の振り分け</li>
<li>処理後にループ先頭に戻る</li>
</ul>
<p>label as value があれば、switch文をジャンプテーブルへのgotoで置き換える事ができます。</p>
<pre class="prog">
    static const void *JUMPTABLE[] = {&amp;&amp;CODE_ADD, &amp;&amp;CODE_SUB, ... , &amp;&amp;CODE_END};

    code = *code_pc++;
    goto *JUMPTABLE[code];

CODE_ADD:
    //足し算処理.
    code = *code_pc++;
    goto *JUMPTABLE[code];

CODE_SUB:
    // 引き算処理
    code = *code_pc++;
    goto *JUMPTABLE[code];
    ...
CODE_END:
</pre>
<p>これで、バイトコード一命令当たりのジャンプをひとつに減らす事ができました。このように、ジャンプテーブルを作って無条件ジャンプすることを computed goto というそうです。</p>
<p>この辺については、YARV開発者の笹田さんが <a href="http://jp.rubyist.net/magazine/?0008-YarvManiacs">YARV Maniacs 【第 3 回】 命令ディスパッチの高速化</a> という記事で詳しく説明されています。 </p>
</div>
<div class="section">
    <h3><a id="id2" name="id2">どれくらい効果があるのか</a></h3>
    <p>Python 3.1a1 がリリースされるときに、 Python-dev ML に pybench で計測したベンチマーク結果が投稿されていました。</p>
    <p><a class="reference" href="http://mail.python.org/pipermail/python-dev/attachments/20090308/3b6f20ff/attachment.txt">http://mail.python.org/pipermail/python-dev/attachments/20090308/3b6f20ff/attachment.txt</a></p>
    <p>だいたい3割前後高速になるそうです。ただし、これはベンチマーク上の話であって、実際に利用される時にはインタプリタの速度が全体の実行時間に占める比重が下がるので、そこまで効果は無いそうです。 (同じスレッド上で、Djangoのテンプレートだと7-8%ほど速度が上がったという報告がありました)</p>
</div>
<div class="section">
    <h3><a id="id3" name="id3">まとめ</a></h3>
    <p>Python3.1をビルドするときには、忘れずに --with-computed-gotos を付けましょう！</p>
</div>

<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51393628" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51390187.html">
<title>IPythonでunicodeリテラルを使う</title>
<link>http://dsas.blog.klab.org/archives/51390187.html</link>
<description>
IPythonとは
IPythonとは、Pythonistaの中で絶大な人気を誇るインタラクティブシェルです。
Pythonはもともとインタラクティブシェルを内蔵しているのですが、
IPythonには内蔵のインタラクティブシェルと比べて多くの利点があります。いくつか挙げてみます。

動的補...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-03-13T16:22:08+09:00</dc:date>
<dc:subject>Python</dc:subject>
<content:encoded><![CDATA[<div class="section">
<h3><a id="ipython" name="ipython">IPythonとは</a></h3>
<p>IPythonとは、Pythonistaの中で絶大な人気を誇るインタラクティブシェルです。</p>
<p>Pythonはもともとインタラクティブシェルを内蔵しているのですが、
IPythonには内蔵のインタラクティブシェルと比べて多くの利点があります。いくつか挙げてみます。</p>
<ul>
<li><p class="first">動的補完</p>
<p>変数名などを途中まで入力した状態でTABキーを押すと、残りを補完してくれます。
候補が複数ある時は候補一覧を表示してくれます。</p>
</li>
<li><p class="first">シンタックスハイライト</p>
<p>プロンプトなどに色がつきます。ちょっとうれしいです。</p>
</li>
<li><p class="first">通常のシェルとしても利用可能</p>
<p>IPythonの中で、lsでファイル一覧を見たり、cdでカレントディレクトリを移動したりできます。
!vim のようにエクスクラメーションマークに続いてコマンド名を入力することで、コマンドの実行もできます。
さらに、コマンドの出力がPythonの変数に格納され、Pythonから利用可能になります。Unixの大量のコマンドを使いこなせなかったり、Windowsでコマンドが少ないことが不満だったりするときに重宝します。</p>
</li>
<li><p class="first">よく使う機能を省略形で記述可能</p>
<p>help(o) の代わりに o? でそのオブジェクトのドキュメントが読めます。</p>
<p>func(a, b) の代わりに func a b で関数呼び出しが可能です。</p>
</li>
<li><p class="first">エディタと連携可能</p>
<p><code>ed foo.py</code> のようにすることで、 <code>foo.py</code> を外部エディタで開いて編集できます。
そしてエディタを閉じると、自動的にそのファイルがevalされます。
この機能を使うと、エディタで関数を書く→IPython上で動作を確認する→エディタで関数を修正する、というサイクルでサクサク開発できます。
これに馴れてしまうと、IDEが欲しいと思わなくなります。</p>
</li>
</ul>
</div>
<div class="section">
<h3><a id="id1" name="id1">IPythonでUnicodeリテラルを使う</a></h3>
<p>IPython 0.9.1 でUnicodeリテラルを使おうとすると、次のような問題がありました</p>
<pre class="prog">
$ python
Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49)
[GCC 4.3.2] on linux2
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt; u&quot;あ&quot;
u'\u3042'
&gt;&gt;&gt;
$ ipython
Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49)
Type &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.

IPython 0.9.1 -- An enhanced Interactive Python.
?         -&gt; Introduction and overview of IPython's features.
%quickref -&gt; Quick reference.
help      -&gt; Python's own help system.
object?   -&gt; Details about 'object'. ?object also works, ?? prints more.

In [1]: u&quot;あ&quot;
Out[1]: u'\xe3\x81\x82'
</pre>
<p>コンソールはUTF-8なので&quot;あ&quot; は3byteになっているのですが、それぞれのbyteを一文字と認識してUnicode文字に変換されています。</p>
<p>この問題を追ってみたところ、IPythonがPythonの組み込み関数 <code>compile()</code> を呼び出すときに、文字列をエンコードしてしまっているのに気づきました。
<code>compile()</code> の動作を調べて見たところ</p>
<pre class="prog">
&gt;&gt;&gt; c = compile(&quot;&quot;&quot;u'あ'&quot;&quot;&quot;, &quot;foo.py&quot;, 'single')
&gt;&gt;&gt; c.co_consts
(u'\xe3\x81\x82', None)
&gt;&gt;&gt; c = compile(u&quot;&quot;&quot;u'あ'&quot;&quot;&quot;, &quot;foo.py&quot;, &quot;single&quot;)
&gt;&gt;&gt; c.co_consts
(u'\u3042', None)
</pre>
<p>ビンゴです。</p>
<p>ということで、<code>IPython/iplib.py</code> に次の修正をすることで、IPythonでUnicodeリテラルが気持ちよく使えるようになります</p>
<pre class="prog">
--- iplib.py.old    2009-03-13 15:42:33.000000000 +0900
+++ iplib.py        2009-03-13 15:42:58.000000000 +0900
&#64;&#64; -2019,9 +2019,9 &#64;&#64;
         # this allows execution of indented pasted code. It is tempting
         # to add '\n' at the end of source to run commands like ' a=1'
         # directly, but this fails for more complicated scenarios
-        source=source.encode(self.stdin_encoding)
-        if source[:1] in [' ', '\t']:
-            source = 'if 1:\n%s' % source
+        #source=source.encode(self.stdin_encoding)
+        if source[:1] in [u' ', u'\t']:
+            source = u'if 1:\n%s' % source

         try:
             code = self.compile(source,filename,symbol)
</pre>
<p>Windows (Python 2.6.1, IPython 0.9.1) でもうまく動くか確認して見ました</p>
<pre class="prog">
In [1]: u&quot;あ&quot;
Out[1]: u'\u3042'

In [2]: u&quot;ソ&quot;
Out[2]: u'\u30bd'
</pre>
<p>バッチリです</p>
</div>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51390187" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51389536.html">
<title>bitsliceによる超高速ビット演算</title>
<link>http://dsas.blog.klab.org/archives/51389536.html</link>
<description>bitslice とは
Hack the Cell '09 に参加して知った、Cellに限らず一般的に使えるビット演算の高速化手法について紹介します。
Bitslice と呼ばれる手法では、ビット順を90度回転します。言葉で説明するよりもコードを見たほうが早いので、回転させるコードの例を見てくだ...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-03-11T16:27:40+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<h3><a id="id1" name="id1">bitslice とは</a></h3>
<p>Hack the Cell '09 に参加して知った、Cellに限らず一般的に使えるビット演算の高速化手法について紹介します。</p>
<p>Bitslice と呼ばれる手法では、ビット順を90度回転します。言葉で説明するよりもコードを見たほうが早いので、回転させるコードの例を見てください</p>
<pre class="prog">
int   x[32], y[32]; // x が元のデータ、y が回転後のデータ.
for (int i = 0; i &lt; 32; ++i) {
    int t = 0;
    for (int j = 0; j &lt; 32; ++j)
        t |= ((x[j] &gt;&gt; i) &amp; 1) &lt;&lt; j; // x[j] の i ビット目を
    y[i] = t;                        // y[i] の j ビット目にする
}
</pre>
<p>この変換をすることで、y[0] には x[0] - x[31] の最下位ビットが、 y[1] には 2番目のビットが格納されることになります。</p>
<p>回転することでビット演算が高速になる様を見てみます。</p>
<pre class="prog">
//--
// and 演算

// 通常
for (int i = 0; i &lt; 32; ++i) {
    x[i] &amp;= 3; // load, and, store, 各32回
}

// bitslice
for (int i = 2; i &lt; 32; ++i) {
    y[i] = 0; // store 30回
}

//--
// xor 演算

// 通常
for (int i = 0; i &lt; 32; ++i) {
    x[i] ^= 0xff; // load, xor, store, 各32回
}

// bitslice
for (int i = 0; i &lt; 8; ++i) {
    y[i] = ~y[i]; // load, not, store 各8回
}

//--
// シフト演算
for (int i = 0; i &lt; 32; ++i) {
    x[i] &gt;&gt;= 16; // load, 右シフト, store, 各32回
}

// bitslice
for (int i = 0; i &lt; 16; ++i) {
    y[i] = y[i+16]; // load, store, 各16回
}
</pre>
<h3><a id="id2" name="id2">bitslice はなぜ速いか</a></h3>
<h4><a id="id3" name="id3">無駄なビットに対する演算を省略できる</a></h4>
<p>たとえば、 x ^= 1 (xは32bit整数) という演算は、最下位ビットを反転させているだけで、最下位以外の31bitにはまったく影響がありません。せっかくの32bit演算なのに、実質は1bit演算になってしまっているわけです。</p>
<p>bitslice なら最下位ビットだけを集めた32bitに対して演算するので、32bit演算の能力を無駄にすることがありません。</p>
<h4><a id="id4" name="id4">マスクがいらない</a></h4>
<p>マスクは操作したくないビットを保護するためのものです。操作したいビットが集まっていれば、マスクが不要です。</p>
<p>マスク付きの通常ビット演算とbitsliceでの演算の対応は次のようになります。</p>
<ul class="simple">
<li>and演算は、マスクビットが0の場所への 0 代入に</li>
<li>or演算は、マスクビットが1の場所への 1 代入に</li>
<li>xor演算は、マスクビットが1の場所への not 演算に</li>
</ul>
<h4><a id="load" name="load">load が減る</a></h4>
<p>普通の and や or 演算においてロードが必要なのは、操作しない(マスクされた)ビットを元の値にしておくためです。bitsliceでは全bitに1や0を代入できるので、不要な load を減らすことができます。</p>
<p>load が減るということは、単純に命令数が削減する以上の意味があります。一般的に言って、store命令は遅延して次の命令と並列に実行できるのに対して、load命令は完了するまでloadした値に依存する命令を実行できません。load命令が減ることで、パイプラインストールを減らすことができます。</p>
<h4><a id="id5" name="id5">工夫次第でさらに速く</a></h4>
<p>先ほどの例では、通常のシフト演算を配列内での移動に置き換えていました。しかし、 y[i] = y[i+16] の代わりに y += 16 が許されるのであれば、シフト演算は完全に省略できることになります。</p>
<p>同じように or 演算でも、 y[i] = 0 をする代わりに、次に y[i] を参照する場所を 0 に置き換えることができるかもしれません。状況によって、いろいろな工夫が考えられます。</p>
<h3><a id="id6" name="id6">bitslice が苦手な計算</a></h3>
<p>bitslice では各ビットがバラバラになっているので、ビット単位の演算は得意な代わりに、ビットをまたがる演算が苦手です。たとえば加算や減算は繰り上がりや繰り下がりがビットをまたぐので、bitsliceでは遅くなります。試しに加算を実装してみます</p>
<pre class="prog">
// 通常の演算
for (int i = 0; i &lt; 32; ++i) {
    x[i] += z;
}

// bitslice
int carry = 0;
for (int i = 0; i &lt; 32; ++i) {
    int c;
    c = (carry &amp; y[i]) | (y[i] &amp; z) | (z &amp; carry);
    y[i] = carry ^ y[i] ^ z;
    carry = c;
}
</pre>
<p>ただし、特定の条件では通常の演算に近い速度が出せることもあります。次の例では、CPUに bitcnt() という bit が 1 になっている数を数える命令があると仮定して、配列の合計値を計算しています</p>
<pre class="prog">
// 通常の演算
int sum = x[0]; // load 1回
for (int i = 1; i &lt; 32; ++i) {
    sum += x[i];  // load, add, 各31回
}

// bitslice
int sum = bitcnt(y[0]); // load, bitcnt, 各1回
for (int i = 1; i &lt; 32; ++i) {
    sum += bitcnt(y[i]) &lt;&lt; i; // load, bitcnt, shift, add 各31回
}
</pre>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51389536" width="1" height="1" />
]]>
</content:encoded>
</item>
<item rdf:about="http://dsas.blog.klab.org/archives/51389200.html">
<title>Hack the Cell '09 課題提出しました</title>
<link>http://dsas.blog.klab.org/archives/51389200.html</link>
<description>Hack the Cell '09 に参戦していました。Fixstars社からの結果発表を待ってから成績報告をしようと思っていたのですが、他の参加者の皆さんがどんどんとスコアや素晴らしいテクニックを披露されているので、予定を前倒しして私のスコアとソースコードを公開します。（中身に...</description>
<dc:creator>klab_gijutsu2</dc:creator>
<dc:date>2009-03-10T19:26:19+09:00</dc:date>
<dc:subject></dc:subject>
<content:encoded><![CDATA[<p><a href="http://dsas.blog.klab.org/archives/51368711.html">Hack the Cell '09 に参戦していました。</a>Fixstars社からの結果発表を待ってから成績報告をしようと思っていたのですが、他の参加者の皆さんがどんどんとスコアや素晴らしいテクニックを披露されているので、予定を前倒しして私のスコアとソースコードを公開します。（中身に関してはまた別の記事に書きます）</p>
<h3><a id="id1" name="id1">提出物とスコア</a></h3>
<p><a href="http://lab.klab.org/files/cell/htc09.tar.bz2">ソースコード</a> (試行錯誤の跡が整理されていません)</p>
<p>スコア</p>
<pre class="terminal">
ORIGNAL:         sum=3c927c56, 294030647 ticks
MINE:            sum=3c927c56, 4464381 ticks
ORIGNAL:         sum=2e987a4d, 424155603 ticks
MINE:            sum=2e987a4d, 6440068 ticks
ORIGNAL:         sum=ef1b6aef, 312102737 ticks
MINE:            sum=ef1b6aef, 4738888 ticks
ORIGNAL:         sum=eedd2516, 290055058 ticks
MINE:            sum=eedd2516, 4403913 ticks
ORIGNAL:         sum=f7e967a8, 14366822 ticks
MINE:            sum=f7e967a8, 218363 ticks
ORIGNAL:         sum=1f37a7db, 214216185 ticks
MINE:            sum=1f37a7db, 3252580 ticks
ORIGNAL:         sum=c7d41f36, 294964206 ticks
MINE:            sum=c7d41f36, 4478494 ticks
ORIGNAL:         sum=aa9d2e9f, 259565045 ticks
MINE:            sum=aa9d2e9f, 3941212 ticks
ORIGNAL:         sum=8abd398a, 250844221 ticks
MINE:            sum=8abd398a, 3808729 ticks
ORIGNAL:         sum=a374bd58, 6110290 ticks
MINE:            sum=a374bd58, 92978 ticks
</pre>
<p>倍率としては、約66倍といったところです。ただし、ORIGINALの速度が安定しない(プログラムのアライメントによって実行速度が変化する)ので、倍率は参考程度にとどめておいてください。</p>
<h3><a id="id2" name="id2">今回のコンテストの内容について</a></h3>
<p>課題は、メルセンヌツイスターという乱数生成機の高速化でした。</p>
<p>最適化する対象となる関数はこちらです(一部省略)</p>
<pre class="prog">
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

static unsigned long mt[N]; /* the array for the state vector  */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */

/* ... */

unsigned long genrand_int32(void)
{
    unsigned long y;
    static unsigned long mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */

    if (mti &gt;= N) { /* generate N words at one time */
        int kk;

        for (kk=0;kk&lt;N-M;kk++) {
            y = (mt[kk]&amp;UPPER_MASK)|(mt[kk+1]&amp;LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y &gt;&gt; 1) ^ mag01[y &amp; 0x1UL];
        }
        for (;kk&lt;N-1;kk++) {
            y = (mt[kk]&amp;UPPER_MASK)|(mt[kk+1]&amp;LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y &gt;&gt; 1) ^ mag01[y &amp; 0x1UL];
        }
        y = (mt[N-1]&amp;UPPER_MASK)|(mt[0]&amp;LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y &gt;&gt; 1) ^ mag01[y &amp; 0x1UL];

        mti = 0;
    }

    y = mt[mti++];

    /* Tempering */
    y ^= (y &gt;&gt; 11);
    y ^= (y &lt;&lt; 7) &amp; 0x9d2c5680UL;
    y ^= (y &lt;&lt; 15) &amp; 0xefc60000UL;
    y ^= (y &gt;&gt; 18);

    return y;
}
</pre>
<p>しかし、最適化したコードを実装する側のスケルトンとなる関数は次のような定義になっていました</p>
<pre class="prog">
unsigned int
genrand_mine(int num_rand)
{
  int r = 0;
  /* r = num_rand 個の乱数のチェックサム */
  return r;
}
</pre>
<p>この関数は戻り値として、 num_rand 個の生成された乱数のチェックサムを返す必要があります。</p>
<p>もともとの課題では、「※疑似乱数列は、メルセンヌ・ツイスタの実装 mt19937ar.c と同じ乱数列を生成してください。」となっていたのですが、参加者によって以下のように異なった解釈がされていました。</p>
<ul class="simple">
<li>同じ32bit整数としての乱数を求められている (私はこの解釈をしていました)</li>
<li>乱数のビット順がどうなっていても良い</li>
<li>そもそも配布されているプログラムがチェックサムしか見ていないのだから、チェックサムだけ合ってれば何をしてもOK</li>
</ul>
<p>この解釈の違いが問題になっていたのですが、最終的には現在課題のページにあるように、一番ゆるい「チェックサムが合っていれば何をしてもOK」というルールで優勝・準優勝を決め、きちんと乱数を生成していた人にはFixstars社の判断で「フィックススターズ賞」が送られることになりました。</p>
<p>結果として、今回のコンテストにおいて最適化の方針として3つが生まれました。</p>
<ol>
<li><p>元のコードをそのままSIMD化する</p>
<p>基本は元のプログラムのまま、mt[] の要素を4つひとまとめに処理する。
その後、命令数を削減したりパイプラインを埋めて速度を稼いでいく。
この方法だと、60倍～70倍程度までを目指せます。</p>
<p>元の乱数生成器と同じ32bit整数で乱数を生成するので、フィックススターズ賞ねらいになります。</p>
</li>
<li><p>ビット順を90度入れ替えた bitsliece と呼ばれる構造で乱数を計算する</p>
<p>SPUの128bitレジスタを、32bit整数4つとしてではなくて、1bitが128個あると考えて最適化していきます。命令の組み合わせだけでなくデータ構造をどうするのかにも工夫が必要になります。この方法で100倍を超えた参加者もおられるようです。</p>
<p>この方法では乱数が32bit整数の形では出現しないので、優勝・準優勝ねらいになります。</p>
</li>
<li><p>乱数を生成しないで直接チェックサムを計算する</p>
<p>mt[] の値は 32bit整数を乱数の種として初期化されるので、種と num_rand と組み合わせた 64bitの情報から結果のチェックサム32bitを求めるということが究極的な目標になります。
極端な例を言えば 32bit * 2^64 分のテーブルを用意すれば、O(1) でチェックサムの計算ができる事になります。</p>
<p>私には全く思いつかなかったのですが、 この計算をメモリ制約の中で O(n) 未満で実行する方法が存在するかもしれません。</p>
</li>
</ol>
<p>私は2月は忙しくて全く高速化できなかったので、ルール確定前までに書いていた 1 の方法のプログラムのまま提出しました。
提出締め切り後、同じ1の方法でもあと5%以上高速化する方法が他の参加者のブログで紹介されていて悔しい思いをしています。
次回があればまた参加したいと思います。</p>
<hr>
<div style="margin: 1px 3px 1px 0px; text-align: right;">@methane</div>
<img src="http://counter2.blog.livedoor.com/c?ro=1&act=rss&output=no&id=1623805&name=klab_gijutsu2&pid=51389200" width="1" height="1" />
]]>
</content:encoded>
</item>

</rdf:RDF>
