« 2007年12月 | メイン | 2008年02月 »

2008年01月 アーカイブ

2008年01月07日

Pythonのスレッドの扱い

ずいぶん前に友人とPythonのスレッドの実装の話になって
調べた時の内容が案外レアかもしれないのでメモです。
たぶんRuby1.9に実装されたYARVも大体同じような実装でしょう。

  • PythonのスレッドはOSの提供するネイティブスレッドと直接対応する
  • しかし、CPythonでは同時に動作するスレッドは1個のみ(GiantGlobal Intepreter Lock)
  • したがって遊んでいるCPUコアがあっても1個しか使われない
  • JythonやIronPythonでは複数スレッドが同時に動く
  • それぞれのPythonVMの命令が実行されている間は、Pythonスレッドが切り替わらないことが保証されている
  • スレッドの切り替えはsys.setcheckintervalで設定された値の数(デフォルト100)の命令が実行されるか、I/O待ち、Sleepに入った時に行われる
  • このためCPythonではスレッドセーフのために同期処理を入れなくても大体動くが、不幸にもスレッド切り替えをまたいだ場合はRace Conditionが発生する可能性がある
  • いままでCPythonでも同時に複数のスレッドが動くようにしてほしいという要望が何回も出ているが、拡張モジュールをスレッドセーフにすることを考えると到底無理ということで却下され続けている

ためしにPythonのスレッドを100個作ってみると、
OS上のスレッドは101個(1個はインタプリタのメインスレッド)できているのが確認できます。
Ruby1.8系だといくつスレッドを作ってもOS上のスレッドの数は変わらないのと違うところですね。

参考:
Python C/API リファレンス 8.1 スレッド状態 (thread state) とグローバルインタプリタロック (global interpreter lock)
Python 2.5.1のソースコードのWin32スレッド実装

2008年01月11日

Perl関数のプロトタイプ

Perlの関数をつくるときにプロトタイプを宣言をつけておくと、組み込みのgrep等のブロックを引数に取る 関数のような表記のユーザー関数を作ることができるわけですが んじゃブロック二個取れたりするんだろうかと思ったのですが駄目でした。 そういう場合は明示的にクロージャを作ってから渡す必要があるみたいです。

use strict;

sub foo(&@) {
    my $proc = shift;
    my @args = @_;
    
    $proc->(@args);
}

sub bar (&&) {
    for(@_) {
        $_->();
    }
}

foo {print $_[0]} (1, 2);

my $m1 = "a";
my $m2 = "b";

#bar {print $m1}, {print $m2}; 
    # =< これはnot enough argumentsエラー
#bar {print $m1} {print $m2}; 
    # =< これもcompilation error
bar sub {print $m1}, sub {print $m2}; # =< OK

perldoc - perlsubを読むと、

    sub mygrep (&@)	     mygrep { /foo/ } $a, $b, $c
    sub myrand ($)	     myrand 42
    sub mytime ()	     mytime
の3つの場合のときのみ、構文解析機が特別扱いするそうです。へえへえ。今気づいたんですが関数宣言の際にattributeとしてlvalueを指定すると、左辺値を返す関数とかも作れるそうです。やっぱりPerlは変態ですね。

参考 perldoc - perlsub:

2008年01月17日

Prediction for 2008

プログラミング言語マニアの巣窟Lambda the Ultimate2008の予想トピックが立っています。


(1) 今年のテーマは並列性.たぶんいくつかの研究言語がErlangの先を目指すだろう.
(2) 新しい言語にはキラーアプリ/フレームワークが必要だということが認識されるだろう、Railsのように。言語作者は言語の新規フィーチャーよりもそっちの方に労力を注がなければならないかも。
(3) F# が.NET屋企業によって製品で利用される例が出てくるだろう。

みたいなコメントを起点にいっぱいコメントが付いています。

(1)については先年の年末にPLINQが正式リリースされたり、どうやら既定コースになりそうです。今のところ軽量言語がGlobal Interpreter LockでCPUを1個しか使えない呪いのために乗り遅れているのがどこかで差になってくるかもしれませんね。
軽量言語側ではMultiVMでどうにかしようという話もあるようですがさてどうか。変わりどころではPythonにpprocessというforkとipcで並列map処理を行うライブラリなんかがあります。こういう路線が穏当なところでしょうか。

(2)についてはそうとしかいいようがありません。誰が3年前にCNETにRubyのニュースが連日掲載されるようなことを予想しえたでしょうか。キラーアプリの存在はかくも重要のようです。

(3)についてはScala ! Scala !というコメントがいっぱいついています。個人的な感触ではScalaの中途半端具合よりはF#のOcamlスタイルのほうが好みなのですが(1)の並列処理と関数型言語は割合相性がいいのでそういう点で期待できるかもしれません。しかしF#はドキュメント少ないのはもう少しなんとかならないかというのとScalaのドキュメントがPDFだらけなのもなんとかならないでしょうか。

個人的には(1)に関係していままで無理やりDBMSに押し込んでいたトランザクションがユーザーコードにはみ出してくることに伴い、分散トランザクションの復権が来るんじゃないかなあと思い、あわててJim Grayのトランザクションの本を読んでいます。あとはDSLやAnnotationの限界がどこかで来ることは間違いないので、Metaluaのようなメタプログラミングへのアプローチがどこかで浮上するのではないかと思います。

2008年01月30日

Jythonをちゃんと試してみた

少し考えるところがあって次のようなJVM上で動くスクリプト言語を実際にいろいろ試しました。比較したのは以下の4つで、今回の場合、主にファイル入出力と文字列処理が評価のターゲットです。 それ以外の評価軸の場合、また何か考える必要があるかもしれません。

  • Groovy
  • Rhino
  • Jython
  • Scala

Aspects

  • ファイル入出力: とにかくBufferdInputStreamとか書かなくて良いか
  • とっつきやすさ: 初見でリファレンスのみでどのくらいかけるか
  • threading: 同様にいちいちThreadクラスとか使わなくてもいいか
  • テキスト処理: 正規表現等が手軽かどうか

Comparision

File IO とっつきやすさ threading テキスト処理
Groovy
Rhino
Jython
Scala

今回は、あんまり安定してなさそうなJRubyは当初から評価から外しました。いろいろ考えるとJythonがいいなあというところに落ち着きました。

Jython

言語仕様がCPythonの2.2相当で止まっていますが、実際2.4や2.5の機能はなくてもたいして問題ではないでしょう。巷にCPython用のライブラリがかなり大量にあるのを流用できるのが良いところです。また、少なくとも今回の評価のタスクについてはJavaのクラスライブラリを呼び出さずに、Jython内のみで完結できたのもポイント高いです。

懸念としてはCPythonと比べるとずいぶん標準ライブラリが少ないことでしょうか。たりないところは、Javaのクラスライブラリを使えばいいので実用的にはさして問題ないでしょう。
また、元々の開発者がMicrosoftに移動してIronPythonの開発に勤しんでいるため、Jythonについてはほとんど開発が止まっています。しかし今のところ動作が変ということは特にないように見えます。日本語codecもCPython 2.3からのフィーチャなので、JythonではJavaの文字コード管理を使うことになります。

また、CPythonと異なり、SMP環境では同時に複数のスレッドが実行可能なところもよいところです。ためしにDualCoreマシンで2個スレッドを立ててBusyLoopすると、きっちりCPU使用率が100%になります。これがCPythonではがんばっても50%にしかなりません。

使い方も簡単です。 インタプリタを起動するには

java -jar jython.jar 
Javaコードの中から実行するときは、jython.jarをクラスパスに入れて
import org.python.core.PyException;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

public class RunJython {

    public static void main(String[] args) throws PyException {
        PythonInterpreter interp = new PythonInterpreter();
    	
    	interp.execfile(args[0]);
    }
}
jarファイル一個をクラスパスに入れておけばよいので、platform dependentになってしまうCPythonのPyInstallerと比べても大変簡単です。

注意点としてgenaratorを使う場合

from __future__ import generators
が必要です。 また、日本語コーデックが同梱されたのはCPython2.3からなので、日本語コーデックも別途必要になるかもしれません

というわけでJython結構良いんでは?という話でした。 追記:日本語出力の問題を修正した2.2.1rc1が出てるみたいです。こちらを使わないとコンソールなどに日本語をうまく表示できないようでした。

続きを読む "Jythonをちゃんと試してみた" »