2012年2月19日日曜日

生産性を上げる魔法の道具

Apple Keyboard を購入しました。日本語、テンキー付きでコンピュータと USB 接続するタイプです。もちろん Mac 用に使うのが普通のところを今回は Ubuntu 10.04 で試してみました。

システム -> 設定 -> キーボード -> レイアウト
とたどって、キーボードの形式を"Apple Aluminium Keyboard (JIS)"として
  • Alt/Window キーの挙動: Control is mapped to Alt keys, Alt is mapped to Win keys
  • CapsLock キーの挙動: Make CapsLock an additional ESC
  • Ctrl キーの位置: Make CapsLock and additional  Ctrl
と設定しました。小指ならどちらでも Ctrl キーが使える、逆に CapsLock を使わないようにする、という感じの設定です。どうやら fn キーは使えないようですが大した問題じゃないとは思います。

研究室では一年近く Logicool の製品 を使っていたのですが、自室の Apple Keyboard (こっちは US タイプ)に比べると明らかに鍵打が遅かったのでちょっと思い切って浮気してみました。テンキー付きのこの製品は bluetooth 接続するタイプのものに比べてかちゃかちゃ感が抑えられていて、キーを叩いたときの力がより無駄なく伝わっているような気がします。もちろん Logicool のやつより速く打てます。ストロークが違うんだよね。たぶん。

USB 端子が側面に付属しているのも嬉しいですね。どうも USB メモリは認識されないようですが….…。

ところで、本屋で立ち読みして実に面白いと思ったので『Python クックブック』(第2版)を購入しました。Python の言語仕様に関連する項目からテクニカルに役立つものまで、実に多彩なレシピが載っています。訳は原著者の妙なハイテンションすら伝わってくるような自然さです。単にマニュアル的な本というわけではなく、目下の課題に対して解法を与え、どうすれば Pythonic な書き方が出来るのかごくごく丁寧に説明してくれます。Python の基本的な使い方を知っている人なら何がしかの役立つ情報が得られると思います。第2版の段階では Python 2.4 までを想定して書かれているので、2.5 以降とは状況が違っているような部分もあるのかもしれません。原書はすでに第3版が出ており、2.6 から 3.x までに対応しているようです。

まだざっと目を通した段階ですが、すでにいくつかのレシピを今書いているプログラムに反映させました:os.popen() なんて関数が存在するとは知らなかったです(恥ずかしながら)。これまでは C で popen() 使って gnuplot を呼ぶ関数を書いた後 DLL を作って ctypes.cdll で読み込んでいたのですが、os モジュールによっていくつもの手順が省けるようになりました。まあしょぼい例ではありますが、『クックブック』をパラパラと眺めていたときに見つけることが出来て良かったです。今後もお世話になる予感。

2012年2月16日木曜日

Cython 素敵

Cython なるものを使い始めました。これはちょっと一言で表し切るのが難しいのですが、Python とほとんど同じ文法を使いつつも C 言語並みの実行速度を得る事が出来るようなプログラムのことです。実物を見てもらった方が早いと思うので、今日から取り組み始めた Project Euler の第9問目を題材にしてごく簡単に説明します。

問題はこうです:和がちょうど 1000 になるようなピタゴラスの三つ組の積を求めよ。

ひとまず、何も考えずに下のようなスクリプトを書きました。

#pe9_job_normal.py
def job():
    for i in range(1, 1001):
        for j in range(i+1, 1001):
            for k in range(j+1, 1001):
                if i**2 + j**2 == k**2 and i + j + k == 1000:
                    return i*j*k

#pe9_normal.py
import pe9_job_normal
print pe9_job_normal.job()

time python pe9_normal.py とした結果は
real    0m36.493s
user    0m36.172s
sys    0m0.046s
で、体感としてはちょっと待たされたという感じでした。

肝心の Cython を利用したコードは次の通りです。

#pe9_job_cython.pyx
def job():
    cdef int i, j, k
    for i in range(1, 1001):
        for j in range(i+1, 1001):
            for k in range(j+1, 1001):
                if i**2 + j**2 == k**2 and i + j + k == 1000:
                    return i*j*k

#pe9_cython.py
import pyximport; pyximport.install()
import pe9_job_cython
print pe9_job_cython.job()

元のスクリプトとの相違点は3カ所あります。1つはループ計算をする関数が .py ではなく .pyx ファイルに書かれていること。そのファイルの 2 行目では cdef int という C 言語ライクな型宣言がなされています。この .pyx ファイルを import pyximport することで pe9_cython.py にインポートしています。ただこれだけのことですが、実行結果は
real    0m0.381s
user    0m0.255s
sys    0m0.074s
となり、およそ 100 倍の速度を得ています。ループ計算中に頻繁に用いられる変数の型を決めてしまう事で、実行速度が劇的に改善される事が分かりました(むしろ Python はどんだけ遅いんだと思ってしまうくらい)。range 関数を使う場合は上のコードのようにループ変数を cdef することで最適化が行われるそうです。

Cython のドキュメントなどによると元々は Sage を開発する目的で作られたとのことで、確かに Python みたいな書きやすさと C に匹敵する速さがあれば開発スピードも実行速度も申し分ないのだろうと想像は出来ます。表面上は C に似ているとはいえ、コンパイルしなくていいというだけでも心理的な負担はかなり少ないです。

Cython については今日気まぐれで使い始めただけなので、まだ色々分かってません。Python のリストや辞書をどう扱ったらいいのかとか、pure C との使い分けをどうするかとか理解したいです。今のところは Python スクリプトを気楽に高速化するための便利システムという程度の認識ですが、今後はもっと入れ込んだりするのかも知れません。なんか分かったらまた書きます。

Python 関連の記事ばっかりになる悪寒がする orz

*追記 @ Feb. 17
Wikipedia の 関連ページ を見てみたらほとんど同じような内容が書かれていてショック……。先に確認しておけば良かった。

2012年2月15日水曜日

The Python Challenge

前々から気になっていた The Python Challenge に取り組み始めました。これは、問題が出題されているページに隠されている次ページへ行くためのキーワードを、主に Python を使って探し出す一連のクイズ集です。言葉にすると分かりにくいかもしれないですが、例えば、1 問目のページに載ってる画像からある文字列を読み取るとか、そんな感じのものです。宝探しみたいなもの。今のところ全部で 34 問あるうちの 12 問目まで来ました。

ちょいちょい「これはプログラムの問題じゃないな」ってのも混ざっていますが、だいたいどの問題も良い勉強になりますね。正規表現の使い方とか、PIL の扱いとか。ヒントを求めるためにどうしてもページのソースを見るようになるので、自然と HTML の文法とかにも慣れてきます。問題を解いて初めて閲覧可能になる解答ページも非常に充実していて、別解が山のように載っているので(場合によっては他言語での解き方とかも議論されてます。Ruby とか bash とか)感心させられる事しきりです。自分がいかに Pythonic なコードを書けていないか痛感する……。可読性を保つ限りで簡潔に書く、ってのが楽しくも難しいところであります。

ipython, numpy, scipy, matplotlib, PIL (and sympy) の組み合わせが最強すぎて ipython シェルから出て来れません。os(.system), shutil モジュールの存在もその一因かな。