YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

OCamlMPIをインストールする(Snow Leopard編)

はじめに

Ubuntu 10.04でのインストールはできたけれど、普段の開発OSであるMac OS X 10.6でもインストールしたい。これがハマったのなんのって。

環境

Mac OS X 10.6.3 + MacPorts 1.8.2 がベース。

gcc 4.2.1 (Apple Inc. build 5659)
make 3.81 (i386-apple-darwin10.0)
ocaml 3.11.2
omake 0.9.8.5 (release 3)
MPI MPICH2 1.0.8 Revision1 (MacPorts)

インストール

MPICH2のインストール

紆余曲折あったもののMPICH2をインストールする。(Appendix参照)

$ sudo port install mpich2
--->  Computing dependencies for mpich2
--->  Fetching mpich2
--->  Verifying checksum(s) for mpich2
--->  Extracting mpich2
--->  Applying patches to mpich2
--->  Configuring mpich2
--->  Building mpich2
--->  Staging mpich2 into destroot
--->  Installing mpich2 @1.0.8_1+darwin
--->  Activating mpich2 @1.0.8_1+darwin
--->  Cleaning mpich2

非常にすんなり入ってくれた。

Makefileの設定

まず最初にインストール先のディレクトリを作成する。

$ sudo mkdir /opt/local/lib/ocaml/ocamlmpi

そしてREADMEにあるように設定を変更する。

-DESTDIR='ocamlc -where'/ocamlmpi
-MPIINCDIR=/usr/local/lib/mpich/include/
-MPILIBDIR=/usr/local/lib/mpich/lib/LINUX/ch_p4
+DESTDIR=/opt/local/lib/ocaml/ocamlmpi
+MPIINCDIR=/opt/local/include/mpich2
+MPILIBDIR=/opt/local/lib
...
mpi.cma: $(OBJS)
-        $(OCAMLC) -a -o mpi.cma -custom $(OBJS) -cclib -lcamlmpi -ccopt -L$(MPILIBDIR) -cclib -lmpi
+        $(OCAMLC) -a -o mpi.cma -custom $(OBJS) -cclib -lcamlmpi -ccopt -L$(MPILIBDIR) -cclib -lmpich
...
mpi.cmxa: $(OBJS:.cmo=.cmx)
-        $(OCAMLOPT) -a -o mpi.cmxa $(OBJS:.cmo=.cmx) -cclib -lcamlmpi -ccopt -L$(MPILIBDIR) -cclib -lmpi
+        $(OCAMLOPT) -a -o mpi.cmxa $(OBJS:.cmo=.cmx) -cclib -lcamlmpi -ccopt -L$(MPILIBDIR) -cclib -lmpich
...
testmpi: test.ml mpi.cma libcamlmpi.a
-        ocamlc -o testmpi unix.cma mpi.cma test.ml -ccopt -L.
+        ocamlc -cc mpicc -o testmpi unix.cma mpi.cma test.ml -ccopt -L.

DESTDIRはデフォルトだと `ocamlc -where` を使って指定してあるけれど、このままだとMac OS Xだとエラーになります。(Appendix参照)
あと参考のURLにあるように、ocamlmpiはMPICHを使う前提でMakefileが書かれてるので、MPICH2を使う場合は-lmpiとなってるところを全部-lmpichとして、libmpich.aを呼ぶようにしてあげないといけないです。あとテストのところにあるようにocamlcのオプションでも"-cc mpicc"が必要です。

ビルド

上記設定をしてあげればすんなりビルドは通る!

$ make all
gcc -I`ocamlc -where` -I/opt/local/include/mpich2 -O -g -Wall   -c -o init.o init.c
gcc -I`ocamlc -where` -I/opt/local/include/mpich2 -O -g -Wall   -c -o comm.o comm.c
gcc -I`ocamlc -where` -I/opt/local/include/mpich2 -O -g -Wall   -c -o msgs.o msgs.c
msgs.c: In function 'caml_mpi_send':
msgs.c:40:5: warning: implicit declaration of function 'caml_enter_blocking_section'
...
Warning Y: unused variable myself.
ocamlc -a -o mpi.cma -custom mpi.cmo -cclib -lcamlmpi -ccopt -L/opt/local/lib -cclib -lmpich
ocamlopt -c mpi.ml
File "mpi.ml", line 329, characters 6-12:
Warning Y: unused variable myself.
ocamlopt -a -o mpi.cmxa mpi.cmx -cclib -lcamlmpi -ccopt -L/opt/local/lib -cclib -lmpich

$ sudo make install
cp mpi.mli mpi.cmi mpi.cma mpi.cmxa mpi.a libcamlmpi.a /opt/local/lib/ocaml/ocamlmpi

なんかwarning出てるけど気にしない。

テスト

ビルドができたらいよいよテスト。

MPICH2を実行する準備

ここでもMPICH2を使ったことによる変更が必要になります。再びMakefileを編集します。

test: testmpi
-        mpirun -np 5 ./testmpi
+        mpiexec -np 5 ./testmpi

一応mpirunでもいいらしいけど、MPICH2ではmpiexecを使いましょう。またMPICH2自身の設定もします。まず $HOME へ移動して .mpd.conf を作成します。ユーザのみ読み書き可能な設定にしておかないとうるさいので一応モードも変更。

$ cd $HOME
$ vi .mpd.conf
MPD_SECRETWORD=mr45-j9z
$ chmod 600 .mpd.conf

そして mpd を起動します。

$ mpd &

これでいよいよテストを実行します。

テストの実行
$ make test
mpiexec -np 5 ./testmpi
0: comm_size = 5
1: comm_size = 5
2: comm_size = 5
3: comm_size = 5
4: comm_size = 5
0: sending aa
1: received aa, resending aaa
2: received aaa, resending aaaa
3: received aaaa, resending aaaaa
...
dims_create 60 [ 3 0 5 ] = [ 3 4 5 ]
0: my wtime is 1274881941.944
2: my wtime is 1274881941.944
1: my wtime is 1274881941.944
3: my wtime is 1274881941.944
4: my wtime is 1274881941.944

無事テストが動きました!これでMac OS Xでもocamlmpiが使えるようになりました。
以下は悪戦苦闘の記録です。

Appendix

MPICH2を使っていきなりビルドはできません

最初MPICH2 (1.0.8)を使ってインストールしたら、まさに下記リンクにあるバグ踏んだ。

これは一筋縄ではいかないです。

$ make testmpi
ocamlc -o testmpi unix.cma mpi.cma test.ml -ccopt -L.
File "test.ml", line 144, characters 6-9:
Warning Y: unused variable res.
$ ./testmpi
[cerbera:08832] *** Process received signal ***
[cerbera:08832] Signal: Segmentation fault (11)
[cerbera:08832] Signal code: Address not mapped (1)
[cerbera:08832] Failing at address: 0x440000b0
[cerbera:08832] [ 0] 2   libSystem.B.dylib                   0x00007fff8140780a _sigtramp + 26
[cerbera:08832] [ 1] 3   ???                                 0x0000000000000000 0x0 + 0
[cerbera:08832] [ 2] 4   testmpi                             0x0000000100000a3a caml_mpi_init + 142
[cerbera:08832] [ 3] 5   testmpi                             0x0000000100008324 caml_interprete + 6455
[cerbera:08832] [ 4] 6   testmpi                             0x000000010000a2f6 caml_main + 877
[cerbera:08832] [ 5] 7   testmpi                             0x000000010001b9c4 main + 12
[cerbera:08832] [ 6] 8   testmpi                             0x0000000100000984 start + 52
[cerbera:08832] [ 7] 9   ???                                 0x0000000000000001 0x0 + 1
[cerbera:08832] *** End of error message ***
Segmentation fault
MPICHも普通にビルドするとこける(MacPorts)

じゃあ、といってMacPortsのMPICH 1.2.7p1はビルド出来ない。

$ sudo port install mpich
--->  Computing dependencies for mpich
--->  Fetching mpich
--->  Verifying checksum(s) for mpich
--->  Extracting mpich
--->  Configuring mpich
--->  Building mpich
Error: Target org.macports.build returned: shell command " cd "/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_science_mpich/work/mpich-1.2.7p1" && /usr/bin/make -j4 " returned error 2
Command output: a - p4_tsr.o
a - p4_mon.o
a - p4_broadcast.o
...
ranlib /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_science_mpich/work/mpich-1.2.7p1/lib/libmpich.a
Exit status from make was 2
make[2]: *** [mpilib] Error 1
make[1]: *** [mpi-modules] Error 2
make: *** [mpi] Error 2

Error: Status 1 encountered during processing.
Before reporting a bug, first run the command again with the -d flag to get complete output.

さらにゴリ押しして再度port install mpichすると

$ sudo port install mpich
...
ld: duplicate symbol _MPIR_Setup_base_datatype in /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_science_mpich/work/mpich-1.2.7p1/lib/libmpich.a(initdte.o) and /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_science_mpich/work/mpich-1.2.7p1/lib/libpmpich.a(initdte.o)
collect2: ld returned 1 exit status
make[4]: *** [overtake] Error 1
make[3]: [linktest1] Error 2 (ignored)
Could not link a C program with MPI libraries
...
MPICHはソースからのビルドもすんなりはいかない

じゃあさらに、ということで使うgcc変更して*1ソースから自前でビルドするのも上手くいかない。

$ ./configure
...
$ make
...
ranlib: file: /Users/ymotongpoo/lib/mpich-1.2.7/lib/libmpich.a(sendutil.o) has no symbols
ranlib: file: /Users/ymotongpoo/lib/mpich-1.2.7/lib/libmpich.a(mpich2_fileutil.o) has no symbols
ranlib: file: /Users/ymotongpoo/lib/mpich-1.2.7/lib/libmpich.a(sendutil.o) has no symbols
ranlib: file: /Users/ymotongpoo/lib/mpich-1.2.7/lib/libmpich.a(mpich2_fileutil.o) has no symbols
make mpi-lib-test
make profileliblink
Testing that MPI applications can be linked...
make linktest
make overtake
/Users/ymotongpoo/lib/mpich-1.2.7/bin/mpicc -DMPID_NO_FORTRAN -DUSE_SOCKLEN_T -DHAVE_MPICHCONF_H  -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DUSE_STDARG=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_LONG_LONG_INT=1 -DHAVE_PROTOTYPES=1 -DHAVE_SIGNAL_H=1 -DHAVE_SIGACTION=1 -DHAVE_SLEEP=1 -DHAVE_SYSCONF=1   -c overtake.c
/Users/ymotongpoo/lib/mpich-1.2.7/bin/mpicc -DMPID_NO_FORTRAN -DUSE_SOCKLEN_T -DHAVE_MPICHCONF_H  -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DUSE_STDARG=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_LONG_LONG_INT=1 -DHAVE_PROTOTYPES=1 -DHAVE_SIGNAL_H=1 -DHAVE_SIGACTION=1 -DHAVE_SLEEP=1 -DHAVE_SYSCONF=1   -c test.c
/Users/ymotongpoo/lib/mpich-1.2.7/bin/mpicc  -o overtake overtake.o test.o 
ld: duplicate symbol _MPIR_Init_dtes in /Users/ymotongpoo/lib/mpich-1.2.7/lib/libmpich.a(initdte.o) and /Users/ymotongpoo/lib/mpich-1.2.7/lib/libpmpich.a(initdte.o)
collect2: ld returned 1 exit status
make[4]: *** [overtake] Error 1
make[3]: [linktest1] Error 2 (ignored)
Could not link a C program with MPI libraries
make[3]: *** [linktest1] Error 1
make[2]: *** [linktest] Error 2
make[1]: *** [mpi-lib-test] Error 2
make: *** [mpi] Error 2
OCamlMPIのMakefile書き換えないためのエラー
  • make installの部分

cpコマンドでこけます。

cp mpi.mli mpi.cmi mpi.cma mpi.cmxa mpi.a libcamlmpi.a `ocamlc -where`/ocamlmpi
usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file
       cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory
make: *** [install] Error 64
  • make testの部分

大量の参照エラーが出ます。

$ make test
ocamlc -o testmpi unix.cma mpi.cma test.ml -ccopt -L.
File "test.ml", line 144, characters 6-9:
Warning Y: unused variable res.
Undefined symbols:
  "_MPI_Bcast", referenced from:
      _caml_mpi_broadcast in libcamlmpi.a(collcomm.o)
      _caml_mpi_broadcast_int in libcamlmpi.a(collcomm.o)
      _caml_mpi_broadcast_float in libcamlmpi.a(collcomm.o)
      _caml_mpi_broadcast_intarray in libcamlmpi.a(collcomm.o)
      _caml_mpi_broadcast_floatarray in libcamlmpi.a(collcomm.o)
  "_MPI_Wtime", referenced from:
      _caml_mpi_wtime in libcamlmpi.a(init.o)
  "_MPI_Comm_split", referenced from:
      _caml_mpi_comm_split in libcamlmpi.a(comm.o)
...
      _caml_mpi_reduce_intarray in libcamlmpi.a(collcomm.o)
      _caml_mpi_reduce_float in libcamlmpi.a(collcomm.o)
      _caml_mpi_reduce_floatarray in libcamlmpi.a(collcomm.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
File "test.ml", line 1, characters 0-1:
Error: Error while building custom runtime system
make: *** [testmpi] Error 2

*1:MacPortsだとMac OS Xに最初から入ってるgcc-4.2を使う