nDiki : PDL

2003年12月4日 (木)

[ Perl ] PDL::Math::eigens

固有ベクトルは返り値の行列に「行ベクトル」として格納されているのか。 列ベクトルだと思ってコーディングしてあったので、残りの全ての計算が全部嘘だったという事が判明。 アウチ。

修正自体は、1個所 xchg(0, 1) するだけ。

[ 12月4日全て ]

2004年2月19日 (木)

[ Perl ] PDL::PP で C extension を書く

PDLを使ったPerl数値処理プログラムによりインタラクティブ性が求められるようになってきたので、一部をCで書いて高速化する事を検討。 問題は Linux でも Windows + ActivePerl でもすんなり動くかどうか。

.pd ファイルを書く

とりあず PDL::PP のサンプルから sumit 関数あたりを MathEx.pd に書いておく。

Makefile.PLを修正する

Foo::Bar パッケージの中の Foo::Bar::Math の一部を Foo::Bar::MathEx に移して、C extension 化したい。 ということで lib/Foo/Bar/MathEx.pd として、Makefile.PL の各種設定をしてみる。

がどうもうまくいかない。 PDL::PPMakefile.PLサポートは、Makefile.PL と同じ位置に .pd がある事を想定しているようなので、いろいろと小細工をしなければならない。 一方 PerlXS は Foo::Bar のベース名から Bar.so を作る前提になっているようで、これまたパッケージの中の一部のモジュールをどうもXS化しにくい。

Makefile.PLを作る

Perl の ext/SDBM_File を真似て、子 Makefile.PL を使ってみることにした。

 Foo-Bar-x.xx
   |
   +- Makefile.PL
   |
   +- lib
   |    |
   |    +- Foo
   |         |
   |         +- Bar.pm
   |         |
   |         +- Bar
   |              |
   |              +- Math.pm
   |              |
   |              +- MathNoEx.pm
   |              |
   |              ...
   |
   |
   +- blib/...
   |
   +- MathEx
   |    |
   |    +- Makefile.PL
   |    |
   |    +- MathEx.pd
   ...

パッケージディレクトリの下に MathEx ディレクトリを作り、そこに Makefile.PL と MathEx.pd を置く。 Makefile.PL は MathEx.pd 専用になるので、PDL::PP の標準的なものでOKになる。

全体のパッケージング・PPM化・インストール等が面倒にならないかと心配したが、Foo-Bar パッケージ化で perl Makefile.PL、make xxx を実行すれば子Makefile.PLまできちんと面倒をみてくれる。 MathEx 以下でビルドしたものもパッケージの blib に一緒に入れてくれるし(=一緒にインストールできる・PPM化できる)。 逆に make dist の際には子Makefileの方は余計なとりまとめはしないで、親Makefileが一括して tar.gz に入れてくれる。 これはよい。 MathEx.pd もきちんと Foo/Bar/MathEx.so になった。

XSが使えない環境との両対応

XSが使えない環境のために、PerlとPPの両方で関数を書いておく。 XSが使えれば MathEx を、使えなければ MathNoEx.pm を使うように。 表向きのAPIは Foo::Bar::Math とし、ここで AUTOLOAD を使ってどちらか一方を呼び出すようにする。 間接呼び出しにして遅くなるのはいやなので、シンボルテーブルを直接設定する。

 use vars qw($IMPLEMENT_CLASS $AUTOLOAD);
 BEGIN {
   $IMPLEMENT_CLASS = 'Foo::Bar::MathEx';

   eval "use $IMPLEMENT_CLASS";
   if ($@) {
     warn "Can't load $IMPLEMENT_CLASS: $@";
     $IMPLEMENT_CLASS = 'Foo::Bar::MathNoEx';
     eval "use $IMPLEMENT_CLASS";
     die $@ if $@;
   }
 }

 sub AUTOLOAD {
   my $name = $AUTOLOAD;
   $name =~ s/.*://;
   my $implement = $IMPLEMENT_CLASS . '::' .$name;
   no strict "refs";
   *{$name} = \&{$implement}; # ここでシンボルテーブル設定
   return &{$implement}(@_);
 }

最初は、AUTOLOAD の最後の行で die したら、trap してエラーメッセージ中のパッケージ名(Foo::Bar::MathEx や Foo::Bar::MathNoEx)を呼び出された Foo::Bar::Math に置換して die し直すようにしようかと思ったが面倒なのでやめ。

ActivePerl 5.6 + Visual C++ 6

使っているWindows BOX には Visual C++ 6 が入っているので、XSも問題なくビルドでき PDL extension もうまく動いた。

 PPM化までここで済ませば、他のPCにも持っていけるはず。

さて

これでバシバシPPで書けるわけだが、PPがこれまた難解で最初は苦労しそう。

[ 2月19日全て ]

2004年3月5日 (金)

[ Perl ] PDL 2.4.1 から eigens が固有ベクトルを列ベクトルで返すように

PDLを使う開発中のプログラムを「速いマシンで使いたい」という要望から、オフィスにある Red Hat Linux 8.0 BOX へ昨日インストール作業を行った。

あいかわらず rpm を探してきてインストールするのが面倒。GDを使うのに freetype の開発パッケージを入れようとしたら、CD-ROM に入っている rpm セットだと freetype とその devel のバージョンが違っていてはいらないし。

結局がしがし /usr/local にインストール。 Perl 5.8.2 自体もそのプログラム専用に別途インストールしてCPANモジュールでがしがし依存するものをインストール。

でようやく環境が整って開発中のプログラムをビルドしたら単体テストでこける。 今日数値をチェックしたら、PDL の eigens 関数が今までと転置した固有ベクトル行列を返すようになっていた。 コレ、以前、列ベクトルだと思ったら行ベクトルだったってやつ。それがまた逆になったらしい。

PDLのドキュメントを見ると確かに、2.4.1 でバグフィックスとして列ベクトルに修正されたらしい。 しかし古いPDLもサポートせねばならない。ということでPDLのバージョンを見て 2.4.0 以下のみ xchg かけるように修正して、問題収束。

[ 3月5日全て ]

2004年6月14日 (月)

PDL疎行列

計算しようとしている行列が 2000 x 2000 次元を超えているので、PDLで素直に計算させるとしんどい。 PDLはネイティブに疎行列をサポートしていないので、独自に実装する必要があるので面倒だな(一応 CPANPDL::Sparse というのもあるにはある)。

外部で計算させようかとも思ったが、GNU Octave もネイティブサポートなし。

やはりPDL::PPを使って自前でPDL上に実装するしかないか?

[ 6月14日全て ]

2004年7月20日 (火)

PARActivePerl 5.6.1 build 638 に

昨日 Linux 上で実験してみた PARWindows にも入れてみる。 PDLを使っている関係で ActivePerl は 5.6.1。

インストール

ppm install で入るパッケージは古いので、最新のものを入れておく。 ちょっと手間。

ワンライナーを pp できるところまで動作確認。

モジュール + スクリプトを実行可能形式に

ExtUtils::Makemakerを使ってパッケージ化している開発中のモジュール(スクリプトあり、XS あり)を実行可能形式化してみる。

 perl Makefile.PL
 nmake
 nmake test
 cd blib
 set PERL5LIB=lib;arch (pp の -I オプションが効かなかったので)
 pp -o foo.exe -a lib -a arch -M ... -c  script/foo

Log::Log4perl::Appender::Screen、Jcode::Unicode::NoXS、Unicode::StringGD については依存関係を自動検出できなかったので、それぞれ -M で指定。

できた。動いた。素晴しい。 PDLGD を使っていたのでちょっと不安だったのだがうまく動いて感激。 これでCD-ROMとか USB メモリに入れておいて一発実行とかできる。

[ 7月20日全て ]

2004年8月17日 (火)

ActivePerl 5.8.4 + PDL 2.4.1

挑戦するも、やはりビルドできず。

[ 8月17日全て ]

2004年8月25日 (水)

PAR

  • eval されるモジュール群は Makefile.PL で抽出して、pp の -M オプションで全て指定するように。
  • PAR で実行形式化すると、PDL の slice 呼び出しの結果が lvalue にならなくなってしまった。この間まで PAR しても問題なかったのだが。slice 呼び出しのの結果を一旦一時変数に入れて使うように修正。
[ 8月25日全て ]

2004年9月21日 (火)

ActivePerl 5.8 用 PDL 2.4.1

実は SourceForge.net にあった。 まだ動作確認していないが、問題なければこれで ActivePerl 5.6.1 ともおさらば。

その場合は PPM リポジトリを再構築しなおしであるが。

[ 9月21日全て ]

2004年9月22日 (水)

ActivePerl 5.6.1 -> 5.8.4

PDLの動作確認がとれたのでプロジェクトで使用するバージョンを v5.8.4 に上げることにする。 PPM パッケージ全部作りなおし。4時間ちょいかかった。

ついでに ithreads まわりもチェック。

[ 9月22日全て ]

2005年5月16日 (月)

PDL の bad value と計算速度

PDL は bad value を扱うことができるのだが、どの程度速度に影響がでるであろうか。 ベンチマークを取ってみた。 環境は Debian GNU/Linux sid + pdl 2.4.2-2 + 2672-PHJ

 #!/usr/bin/perl -w
 use strict;

 use PDL;
 use Benchmark;
 my $a = sequence(1000, 1000);
 my $b = sequence(1000, 1000);
 #$a->badflag(1);
 #$b->badflag(1);
 timethis(10, sub { my $c = matmult($a, $b)});

badflag(0)

 timethis 10: 203 wallclock secs
 (198.90 usr +  0.46 sys = 199.36 CPU) @  0.05/s (n=10)

badflag(1)

 timethis 10: 416 wallclock secs
 (400.87 usr +  0.92 sys = 401.79 CPU) @  0.02/s (n=10)

ほぼ半分の速度。 ちなみに bad value サポート無しで PDL をリビルドして試してみたが、bad value 無しの計算では(matmult においては)特に差がなかった。

bad value の必要がないならば、PDL をリビルドした方がいいのかと思ってみたけれど実験した範囲ではかわらないようだ。

[ 5月16日全て ]

About Me

Naney Naney

Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。

About nDiki

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。

#nNote タグがついている記事は他の記事に比べて、より断片的・未整理・不完全なちょっとしたノートです。まだ結論に至っていない考えなども含まれます。頻繁/大幅に更新したり削除したりすることがあります。

※本サイトの内容は個人的見解であり所属組織とは関係ありません。

Other Notes

ナレッジベースアプリケーション Obsidian で書いているノートの一部を notes.naney.org で 公開しています。

最近検索されている記事

月別インデックス
Process Time: 0.069712s / load averages: 0.63, 0.65, 0.45
nDiki by WATANABE Yoshimasa (Naney)
Powered by DiKicker