HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

MPIライブラリ毎のプロセスマッピング指定方法

さっき、ひさびさにIntelMPIを使ってて、プロセスマッピングの指定ってどうやるんだっけと小一時間悩んでしまったので、自分用メモとして残しときます。

IntelMPIの場合、プロセスマッピングを指定するには以下の環境変数を使います。

  • I_MPI_PIN
  • I_MPI_PIN_MODE
  • I_MPI_PIN_RESPECT_CPUSET
  • I_MPI_PIN_RESPECT_HCA
  • I_MPI_PIN_CELL
  • I_MPI_PIN_DOMAIN
  • I_MPI_PIN_ORDER
  • I_MPI_PIN_PROCESSOR_LIST

といってもI_MPI_PINからI_MPI_PIN_RESPECT_HCAまでは通常はデフォルト値のままで良いので、指定するのは後半の4つのみです。

I_MPI_PIN_CELLに指定可能な値は"unit"か"core"のどちらかで、前者は論理コア後者は物理コア単位での割り当てを行うことを指定します。
HyperThreadingが有効な時に、なるべく1rankが使うコアを狭めたいけど同じ物理コアで2rank動かれるのは困る、なんて時にはcoreを指定すれば良さそうです。*1


I_MPI_PIN_DOMAINは1rankが使うコア数を指定するものです。
1ノード16コアの環境で、ノードあたり8プロセス実行とかだったら16/8で2と指定すれば良いのですが、autoに指定しておくとこれと同様な計算を自動的にやってくれます。また、OMP_NUM_THREADSの値と合わせるompというキーワードも使えます。
他にもsocket/core/nodeといった指定もできますし(それぞれ1ソケット/1コア/1ノードあたり1rankを割り当てる)cacheという値を指定すれば、cacheを共有している範囲をdomainとしてその範囲内には1プロセスしか割り当てません。
ただし -n オプションで指定されたプロセス数が、使うノードの範囲内に納まらなかった場合は1domain内に複数のrankが割り当てられることもあります。(その場合はrank0から順に各domainに1rankづつ割り当てて、余ったらまたdomain0から順に割り当ててといった感じになるはず)
それから、auto/ompもしくは明示的なdomainのサイズを指定した場合は続けて :layout という形でdomainのレイアウト方法を指定できます。
これは、compact/scatter/platformの3つの値が指定できて、compactだと同一domainがなるべく近いコアに、scatterだとなるべく遠いコアに割り当てられます。platformにすると単純にBIOSレベルでのcore id順(たぶん/proc/cpuinfoで見える順番)で割り当てられます。

まぁ、色々書いたけど ハイブリッドプログラムなら omp:compactでflat MPIのプログラムなら core にしておけばたいてい大丈夫でしょう。
ハイブリッドプログラムで非privateな領域にやたらとアクセスしてスラッシングが酷いとかなら、omp:scatterも有効かもしれませんが、そもそもそんなプログラムは書き換えるべk


I_MPI_PIN_ORDERはI_MPI_PIN_DOMAINで指定した各ドメインを実際に割り当てる時の順番を指定します。
指定できる値は、compact/scatter/spread/bunchの4つです。
reference manualに非常に分かりやすい解説があったので、詳細は省きますが、たぶんcompactしか使わない。


I_MPI_PIN_PROCESSOR_LISTは、DomainとOrderの組み合わせでは指定できないような面倒なパターンを指定する時に使えます。
例えばrank0から3は同一ソケット上の連続した3つの物理コアを使ってrank4は同じノードの別ソケットを使うとか。
これで細かく指定するのは、コアを余らせて実行するような時なので、普段はあんあり出番は無いです。(ベンチマークとる時はそこそこ使う)

最後に、この辺のプロセスマッピングの状況を出力させるには

export I_MPI_DEBUG=4

を指定しておけばOKです。(正確に4じゃなくても4以上の値ならOK)

*1:でも、そもそもHPC用途だと大抵HT切ってるから使ったこと無いw

Alces Flight

starclusterだのcfnclusterだのをいじっていたら、なんかまた新しいサービスが始まってたようです。

Alces Flight: Effortless HPC is Born (Finally)

AWS marketplaceから起動できるので、これはこれで便利そうですね。


こちらは、starclusterやcfnclusterと違ってアプリのインストール手段を提供しているというのが特長らしくこんな感じの長いソフトの一覧が用意されています。*1

Alces Gridware Software Applications — flight-appliance-docs 1.0 documentation


個人的には興味無しだけど、プログラムをいじらずにひたすら計算する人*2には良いサービスかもしれませんね。


しかし、なぜかスケジューラはOpen grid schedulerが入っているそうで・・・なんでみんなそんなにSGE系のスケジューラが好きなんだろうか。

*1:なんかカテゴリに偏りがある気が・・・

*2:まるで学生時代の私だ:p

starcluster と cfncluster その2

続いてcfnclusterを使ってPCクラスタを作ってみます。starclusterと条件を合わせるために、c3.largeの4ノード構成でやってみます。

インストール(windows native版)

記事を分けたついでに、windows nativeのpythonでもインストールしてみます。

>python -m virtualenv --python=C:\Python27\python.exe cfncluster
>cd cfncluster
>Scripts\activate
>pip install cfncluster
Collecting cfncluster
  Downloading cfncluster-1.2.1.tar.gz
Collecting boto>=2.39 (from cfncluster)
  Using cached boto-2.40.0-py2.py3-none-any.whl
Collecting awscli>=1.10.13 (from cfncluster)
  Downloading awscli-1.10.34-py2.py3-none-any.whl (938kB)
    100% |################################| 942kB 450kB/s
Collecting s3transfer==0.0.1 (from awscli>=1.10.13->cfncluster)
  Downloading s3transfer-0.0.1-py2.py3-none-any.whl
Collecting colorama<=0.3.3,>=0.2.5 (from awscli>=1.10.13->cfncluster)
  Downloading colorama-0.3.3.tar.gz
Collecting rsa<=3.5.0,>=3.1.2 (from awscli>=1.10.13->cfncluster)
  Downloading rsa-3.4.2-py2.py3-none-any.whl (46kB)
    100% |################################| 49kB 1.5MB/s
Collecting botocore==1.4.24 (from awscli>=1.10.13->cfncluster)
  Downloading botocore-1.4.24-py2.py3-none-any.whl (2.3MB)
    100% |################################| 2.3MB 185kB/s
Collecting docutils>=0.10 (from awscli>=1.10.13->cfncluster)
  Downloading docutils-0.12.tar.gz (1.6MB)
    100% |################################| 1.6MB 269kB/s
Collecting futures<4.0.0,>=2.2.0 (from s3transfer==0.0.1->awscli>=1.10.13->cfncluster)
  Downloading futures-3.0.5-py2-none-any.whl
Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli>=1.10.13->cfncluster)
  Using cached pyasn1-0.1.9-py2.py3-none-any.whl
Collecting jmespath<1.0.0,>=0.7.1 (from botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Downloading jmespath-0.9.0-py2.py3-none-any.whl
Collecting python-dateutil<3.0.0,>=2.1 (from botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Downloading python_dateutil-2.5.3-py2.py3-none-any.whl (201kB)
    100% |################################| 204kB 1.6MB/s
Collecting six>=1.5 (from python-dateutil<3.0.0,>=2.1->botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Using cached six-1.10.0-py2.py3-none-any.whl
Building wheels for collected packages: cfncluster, colorama, docutils
  Running setup.py bdist_wheel for cfncluster ... done
  Stored in directory: C:\Users\n_so5\AppData\Local\pip\Cache\wheels\26\c8\b0\3cf98bf7d72a9a63a358cbf094a50092641a70843de01ca155
  Running setup.py bdist_wheel for colorama ... done
  Stored in directory: C:\Users\n_so5\AppData\Local\pip\Cache\wheels\21\c5\cf\63fb92293f3ad402644ccaf882903cacdb8fe87c80b62c84df
  Running setup.py bdist_wheel for docutils ... done
  Stored in directory: C:\Users\n_so5\AppData\Local\pip\Cache\wheels\db\de\bd\b99b1e12d321fbc950766c58894c6576b1a73ae3131b29a151
Successfully built cfncluster colorama docutils
Installing collected packages: boto, futures, jmespath, six, python-dateutil, docutils, botocore, s3transfer, colorama, pyasn1, rsa, awscli, cfncluster
Successfully installed awscli-1.10.34 boto-2.40.0 botocore-1.4.24 cfncluster-1.2.1 colorama-0.3.3 docutils-0.12 futures-3.0.5 jmespath-0.9.0 pyasn1-0.1.9 python-dateutil-2.5.3 rsa-3.4.2 s3transfer-0.0.1 six-1.10.0
You are using pip version 8.0.2, however version 8.1.2 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

あっさりインストールできました。

クラスタの起動

こちらは、cfnclusterを使う前に鍵を作っておく必要があります。
以下のURLへアクセスして「キーペアを作成」というボタンを押します。
https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#KeyPairs:sort=keyFingerprint
名前を付けると、あとは自動的にpemファイルのダウンロードが始まるので、保存しておきます。

続いて、cfnclusterから設定を作成します。cfncluster configureと入力すると、CLI上でウィザードが始まるので、質問に答えていきます。

>cfncluster configure
Cluster Template [default]:
AWS Access Key ID []: QWERTYUIOP{}
AWS Secret Access Key ID []: ASDFGHJKL:"
Acceptable Values for AWS Region ID:
    us-east-1
    cn-north-1
    ap-northeast-1
    ap-southeast-2
    sa-east-1
    ap-southeast-1
    ap-northeast-2
    us-west-2
    us-gov-west-1
    us-west-1
    eu-central-1
    eu-west-1
AWS Region ID []:ap-northeast-1
VPC Name [public]:
Acceptable Values for Key Name:
    CfnClusterTest
Key Name []: CfnClusterTest
Acceptable Values for VPC ID:
    vpc-123n456
VPC ID []: vpc-123n456
Acceptable Values for Master Subnet ID:
    subnet-987f6543
    subnet-12345678
Master Subnet ID []:subnet-987f654

リージョン、鍵ペア、VPC、サブネットIDなどを指定するんですが、それぞれ設定可能な値が選択肢として表示されるので、ここからコピペすればOKです。また、1回選択した内容は保存されているようなので、再度cfncluster configureを実行すると、デフォルトの値として前回使った値が表示されます。

これで、$HOME/.cfncluster/config以下に設定ファイルが作成されるんですが、starclusterと違って上記で入力した値しか書かれていません。
後は、ここのドキュメントを見ながら必要な設定を追記していきます。
Configuration — CfnCluster 1.2.1

今回追記したのは全て[cluster default]セクションの中で、以下の5項目です。
この設定で、4ノード構成のクラスタが立ち上がり、用が無くなったら勝手に落としてくれるはず。
schedulerはデフォルトでは、starclusterと同じくSGEですが、openlava, torque, slurmも使えるとのことなので、慣れてるslurmで試してみることにします。

 compute_instance_type = c3.large
 master_instance_type = c3.large
 initial_queue_size = 4
 max_queue_size = 4
 scheduler = slurm

もし、まったくジョブが流れてなくても何ノードかは常に立ち上げておきたいという時は、initial_queue_sizeに必要なノード数を設定し、

maintain_initial_size = true

という設定を追加します。これで、Autoscalingの設定が変わって、最小ノード数以下まで下げることは無くなるとのこと。



続けてクラスタを起動します。

> cfncluster create mycluster

驚くほど遅いので、一服しながら待ちましょう。今回の構成だと、だいたい15分くらいかかりました。
$HOME/.cfncluster/cfncluster-cli.logにログが吐かれてますが、何か特別時間がかかる処理があるわけではなく、満遍無く遅いようです・・・。
起動が完了したら、次のようにMasterノードのIPアドレスとGangliaのURLが表示されます。

Output:"MasterPrivateIP"="172.31.13.62"
Output:"MasterPublicIP"="52.196.251.236"
Output:"GangliaPrivateURL"="http://172.31.13.62/ganglia/"
Output:"GangliaPublicURL"="http://52.196.251.236/ganglia/"

最初に作ったkeypairを使ってログインしてみましょう。

> ssh ec2-user@52.196.251.236 -i CfnClusterTest.pem

とりあえず、何が入っているのか分からんので適当に試してみたところ、こんな感じでした。

>$ gcc --version
gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ mpirun --version
-bash: mpirun: command not found
$ sbatch --version
-bash: sbatch: command not found
$ which qsub
/opt/sge/bin/lx-amd64/qsub

わざわざスケジューラにslurmを指定したのに、そもそも全部入ってたようです・・・

$ /opt/slurm/bin/sinfo
sinfo: error: s_p_parse_file: unable to status file /opt/slurm/etc/slurm.conf: No such file or directory, retrying in 1sec up to 60sec
$ qconf -sel
ip-172-31-15-101.ap-northeast-1.compute.internal
ip-172-31-15-102.ap-northeast-1.compute.internal
ip-172-31-15-103.ap-northeast-1.compute.internal
ip-172-31-15-104.ap-northeast-1.compute.internal

そして、sinfo(slurmの情報表示コマンド)は使えないのに、qconf(SGEの設定コマンド)は正常に動作するという・・・

MPIの方はどうかというと

$ yum list installed |grep -i mpi
mpich.x86_64                   3.0.4-4.5.amzn1                 @amzn-main
mpich-devel.x86_64             3.0.4-4.5.amzn1                 @amzn-main
openmpi.x86_64                 1.6.4-5.29.amzn1                @amzn-main
openmpi-devel.x86_64           1.6.4-5.29.amzn1                @amzn-main

インストール済なんだけどPATHは通ってないようです。

$ rpm -ql openmpi.x86_64
/etc/openmpi-x86_64
/etc/openmpi-x86_64/openmpi-default-hostfile
/etc/openmpi-x86_64/openmpi-mca-params.conf
/etc/openmpi-x86_64/openmpi-totalview.tcl
/etc/profile.d/openmpi.sh
/usr/lib64/gfortran/modules/openmpi-x86_64
/usr/lib64/openmpi
/usr/lib64/openmpi/bin
/usr/lib64/openmpi/bin/mpiexec
/usr/lib64/openmpi/bin/mpirun
/usr/lib64/openmpi/bin/ompi-clean
・
・
・
$ cat /etc/profile.d/openmpi.sh
function set_openmpi {
    MPI_HOME=/usr/lib64/openmpi
    MPI_BIN=$MPI_HOME/bin
    MPI_LIB=$MPI_HOME/lib
    MPI_MAN=/usr/share/man/openmpi-x86_64
    MPI_INCLUDE=/usr/include/openmpi-x86_64
    MPI_SYSCONFIG=/etc/openmpi-x86_64
    MPI_COMPILER=openmpi-x86_64
    MPI_SUFFIX=_openmpi
    MPI_PYTHON_SITEARCH=/usr/lib64/python2.6/dist-packages/openmpi
    MPI_FORTRAN_MOD_DIR=/usr/lib64/gfortran/modules/openmpi-x86_64
}

function load_openmpi {
    set_openmpi

    export PATH=$MPI_BIN:$PATH
    export LD_LIBRARY_PATH=$MPI_LIB:$LD_LIBRARY_PATH
    export MANPATH=$MPI_MAN:$MANPATH

    export MPI_HOME MPI_BIN MPI_LIB MPI_MAN MPI_INCLUDE MPI_SYSCONFIG
    export MPI_COMPILER MPI_SUFFIX MPI_PYTHON_SITEARCH MPI_FORTRAN_MOD_DIR
}

function unload_openmpi {
    set_openmpi

    export PATH=$(echo $PATH | tr : '\n' | egrep -v "^$MPI_BIN$" | tr '\n' :)
    export LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | tr : '\n' | egrep -v "^$MPI_LIB$" | tr '\n' :)
    export MANPATH=$(echo $MANPATH | tr : '\n' | egrep -v "^$MPI_MAN$" | tr '\n' :)

    unset MPI_HOME MPI_BIN MPI_LIB MPI_MAN MPI_INCLUDE MPI_SYSCONFIG
    unset MPI_COMPILER MPI_SUFFIX MPI_PYTHON_SITEARCH MPI_FORTRAN_MOD_DIR
}

えーっと・・・これmodule経由で使うものなんでは。
というわけで、.bashrcの末尾に以下の一行を追記します。

load_openmpi

でもって、再度ログインすると

$ mpirun --version
mpirun (Open MPI) 1.6.4

Report bugs to http://www.open-mpi.org/community/help/

正常にmpi関連のコマンドが動くようになりました。

一応こっちも一応HPLを流してみましょう。
staclusterの時の残念な結果があるので、まずはBLASの確認

$ yum list installed |grep blas
blas.x86_64                    3.5.0-8.6.amzn1                 @amzn-main
blas-devel.x86_64              3.5.0-8.6.amzn1                 @amzn-main
$ rpm -qi blas.x86_64
Name        : blas
Version     : 3.5.0
Release     : 8.6.amzn1
Architecture: x86_64
Install Date: Wed 23 Mar 2016 11:50:31 PM UTC
Group       : System Environment/Libraries
Size        : 782395
License     : BSD
Signature   : RSA/SHA256, Thu 18 Sep 2014 01:36:21 AM UTC, Key ID bcb4a85b21c0f39f
Source RPM  : lapack-3.5.0-8.6.amzn1.src.rpm
Build Date  : Wed 17 Sep 2014 09:15:24 PM UTC
Build Host  : build-64001.build
Relocations : (not relocatable)
Packager    : Amazon.com, Inc. <http://aws.amazon.com>
Vendor      : Amazon.com
URL         : http://www.netlib.org/lapack/
Summary     : The Basic Linear Algebra Subprograms library
Description :
BLAS (Basic Linear Algebra Subprograms) is a standard library which
provides a number of basic algorithms for numerical algebra.

えーっと・・・Netlib版のBLASなのか・・・
これはさすがにありえんので、OpenBLASをインストールします。

$ sudo yum install openblas -y
Loaded plugins: priorities, update-motd, upgrade-helper
956 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package openblas.x86_64 0:0.2.16-3.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================================================================================================================
 Package                                   Arch                                    Version                                       Repository                             Size
=============================================================================================================================================================================
Installing:
 openblas                                  x86_64                                  0.2.16-3.el6                                  epel                                  5.5 M

Transaction Summary
=============================================================================================================================================================================
Install  1 Package

Total download size: 5.5 M
Installed size: 32 M
Downloading packages:
warning: /var/cache/yum/x86_64/2016.03/epel/packages/openblas-0.2.16-3.el6.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
Public key for openblas-0.2.16-3.el6.x86_64.rpm is not installed
openblas-0.2.16-3.el6.x86_64.rpm                                                                                                                      | 5.5 MB     00:00
Retrieving key from http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
Importing GPG key 0x0608B895:
 Userid     : "EPEL (6) <epel@fedoraproject.org>"
 Fingerprint: 8c3b e96a f230 9184 da5c 0dae 3b49 df2a 0608 b895
 From       : http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : openblas-0.2.16-3.el6.x86_64                                                                                                                              1/1
  Verifying  : openblas-0.2.16-3.el6.x86_64                                                                                                                              1/1

Installed:
  openblas.x86_64 0:0.2.16-3.el6

Complete!
[ec2-user@ip-172-31-13-62 ~]$ sudo yum install openblas-devel -y
Loaded plugins: priorities, update-motd, upgrade-helper
956 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package openblas-devel.x86_64 0:0.2.16-3.el6 will be installed
--> Processing Dependency: openblas-threads(x86-64) = 0.2.16-3.el6 for package: openblas-devel-0.2.16-3.el6.x86_64
--> Processing Dependency: openblas-openmp(x86-64) = 0.2.16-3.el6 for package: openblas-devel-0.2.16-3.el6.x86_64
--> Processing Dependency: libopenblasp.so.0()(64bit) for package: openblas-devel-0.2.16-3.el6.x86_64
--> Processing Dependency: libopenblaso.so.0()(64bit) for package: openblas-devel-0.2.16-3.el6.x86_64
--> Running transaction check
---> Package openblas-openmp.x86_64 0:0.2.16-3.el6 will be installed
---> Package openblas-threads.x86_64 0:0.2.16-3.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================================================================================================================
 Package                                         Arch                                  Version                                     Repository                           Size
=============================================================================================================================================================================
Installing:
 openblas-devel                                  x86_64                                0.2.16-3.el6                                epel                                 88 k
Installing for dependencies:
 openblas-openmp                                 x86_64                                0.2.16-3.el6                                epel                                5.6 M
 openblas-threads                                x86_64                                0.2.16-3.el6                                epel                                5.6 M

Transaction Summary
=============================================================================================================================================================================
Install  1 Package (+2 Dependent packages)

Total download size: 11 M
Installed size: 68 M
Downloading packages:
(1/3): openblas-devel-0.2.16-3.el6.x86_64.rpm                                                                                                         |  88 kB     00:00
(2/3): openblas-openmp-0.2.16-3.el6.x86_64.rpm                                                                                                        | 5.6 MB     00:00
(3/3): openblas-threads-0.2.16-3.el6.x86_64.rpm                                                                                                       | 5.6 MB     00:00
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                         15 MB/s |  11 MB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : openblas-threads-0.2.16-3.el6.x86_64                                                                                                                      1/3
  Installing : openblas-openmp-0.2.16-3.el6.x86_64                                                                                                                       2/3
  Installing : openblas-devel-0.2.16-3.el6.x86_64                                                                                                                        3/3
  Verifying  : openblas-devel-0.2.16-3.el6.x86_64                                                                                                                        1/3
  Verifying  : openblas-openmp-0.2.16-3.el6.x86_64                                                                                                                       2/3
  Verifying  : openblas-threads-0.2.16-3.el6.x86_64                                                                                                                      3/3

Installed:
  openblas-devel.x86_64 0:0.2.16-3.el6

Dependency Installed:
  openblas-openmp.x86_64 0:0.2.16-3.el6                                                openblas-threads.x86_64 0:0.2.16-3.el6

Complete!

あとは、staclusterの時と同じようにHPLのソースをダウンロードしてきて、ビルド&実行します。

$ wget http://www.netlib.org/benchmark/hpl/hpl-2.2.tar.gz
--2016-05-31 14:13:01--  http://www.netlib.org/benchmark/hpl/hpl-2.2.tar.gz
Resolving www.netlib.org (www.netlib.org)... 160.36.131.221
Connecting to www.netlib.org (www.netlib.org)|160.36.131.221|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 539979 (527K) [application/x-gzip]
Saving to: ‘hpl-2.2.tar.gz’

hpl-2.2.tar.gz                              100%[========================================================================================>] 527.32K   598KB/s    in 0.9s

2016-05-31 14:13:03 (598 KB/s) - ‘hpl-2.2.tar.gz’ saved [539979/539979]

$ tar xfz hpl-2.2.tar.gz
$ cd hpl-2.2
$ cp setup/Make.Linux_PII_FBLAS ./

staclusterの時と同じくMake.Linux_PII_FBLASを編集します。(LAdir, LAlibの設定はちょっと変わっています。)

TOPdir       = $(HOME)/hpl-2.2
MPdir, MPinc, MPlib  ->コメントアウト
LAdir=/usr/lib64
LAlib= -L$(LAdir) -lopenblas
CC=mpicc
LINKER=mpicc

そして、makeします。

$ make arch=Linux_PII_FBLAS 2>&1 |tee makelog

HPL.datをstarclusterの時と同様に編集したらジョブ投入

> qsub -cwd -pe mpi 8 -b y mpirun ./xhpl

ところが、こんなエラーを吐いて終了します。

$ cat mpirun.e2
-sh: mpirun: command not found

エラーメッセージから察するに、bashじゃなくてsh経由でジョブを投げようとしているようなので、シェルスクリプトを作ってこっち経由で投げます。

$ cat run.sh
#!/bin/bash
mpirun ./xhpl
$ qsub -cwd -pe mpi 8 run.sh
Unable to run job: warning: ec2-user's job is not allowed to run in any queue

あれ・・・?

$ qconf -sel
no execution host defined

あ、アイドル状態が長すぎて計算ノードが落とされてますね・・・
EC2のマネジメントコンソールを見ると、確かに"Compute"と書かれたインスタンスがterminatedになっています。時間的にも起動して1時間くらい経過していたので、きちんと機能していますね!最大の問題は、この状態から計算ノードを起動する方法が分からんあたり・・・

仕方が無いので、一旦削除してもう一度作り直してみます。
ついでにopenblasのインストールは計算ノード側でもやらないと駄目だったことにも気付いたので改めて作業内容をまとめておきます。

>cfncluster create mycluster
Starting: mycluster
Status: cfncluster-mycluster - CREATE_COMPLETE                                  Output:"MasterPrivateIP"="172.31.6.163"
Output:"MasterPublicIP"="52.192.191.47"
Output:"GangliaPrivateURL"="http://172.31.6.163/ganglia/"
Output:"GangliaPublicURL"="http://52.192.191.47/ganglia/"

>ssh  ec2-user@52.192.191.47 -i CfnClusterTest.pem
$ for i in `qconf -sel`;do ssh $i "sudo yum install openblas openblas-devel -y"
$ wget http://www.netlib.org/benchmark/hpl/hpl-2.2.tar.gz
$ tar xfz hpl-2.2.tar.gz
$ cd hpl-2.2
$ cp setup/Make.Linux_PII_FBLAS ./
$ make CC=mpicc LINKER=mpicc TOPdir=`pwd` MPdir="" MPinc="" MPlib="" LAlib="-L/usr/lib64 -lopenblas" arch=Linux_PII_FBLAS 2>&1 |tee makelog

でもって、さっきと同じようにHPL.datを編集したらジョブを投げます。ただし、load_openmpiはrun.shの中で実行するように変更しました。

$  cat run.sh
#!/bin/bash
load_openmpi
mpirun ./xhpl
$ qsub -cwd -pe mpi 8 run.sh
Your job 1 ("run.sh") has been submitted

ジョブが完走したら、run.sh.o2に結果が出力されます。

$ cat run.sh.o2
================================================================================
HPLinpack 2.2  --  High-Performance Linpack benchmark  --   February 24, 2016
Written by A. Petitet and R. Clint Whaley,  Innovative Computing Laboratory, UTK
Modified by Piotr Luszczek, Innovative Computing Laboratory, UTK
Modified by Julien Langou, University of Colorado Denver
================================================================================

An explanation of the input/output parameters follows:
T/V    : Wall time / encoded variant.
N      : The order of the coefficient matrix A.
NB     : The partitioning blocking factor.
P      : The number of process rows.
Q      : The number of process columns.
Time   : Time in seconds to solve the linear system.
Gflops : Rate of execution for solving the linear system.

The following parameter values will be used:

N      :   40000
NB     :      64
PMAP   : Row-major process mapping
P      :       4
Q      :       2
PFACT  :    Left
NBMIN  :       2
NDIV   :       2
RFACT  :    Left
BCAST  :   1ring
DEPTH  :       0
SWAP   : Mix (threshold = 64)
L1     : transposed form
U      : transposed form
EQUIL  : yes
ALIGN  : 8 double precision words

--------------------------------------------------------------------------------

- The matrix A is randomly generated for each test.
- The following scaled residual check will be computed:
      ||Ax-b||_oo / ( eps * ( || x ||_oo * || A ||_oo + || b ||_oo ) * N )
- The relative machine precision (eps) is taken to be               1.110223e-16
- Computational tests pass if scaled residuals are less than                16.0

================================================================================
T/V                N    NB     P     Q               Time                 Gflops
--------------------------------------------------------------------------------
WR00L2L2       40000    64     4     2             542.05              7.872e+01
HPL_pdgesv() start time Tue May 31 15:30:31 2016

HPL_pdgesv() end time   Tue May 31 15:39:33 2016

--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)=        0.0043542 ...... PASSED
================================================================================

Finished      1 tests with the following results:
              1 tests completed and passed residual checks,
              0 tests completed and failed residual checks,
              0 tests skipped because of illegal input values.
--------------------------------------------------------------------------------

End of Tests.
================================================================================

78.72Gflopsなので、実行効率にして45.5%ですね。starclusterの時と比べると約3倍になってますが、ちょっともの足りない数字です。
まだサイズを増やせば性能が上がる可能性もありますが、c3.largeだとメモリの制約が厳しいので、これより大きいサイズで測定するのは厳しそうです。
あと、OpenBLASの方がAtlasよりは性能が高いとは思いますが、DGEMM単体での性能を測定したわけではないので、まだBLASの性能が不足しているという可能性もありそうです。この辺はそのうち再検証してみましょう。

では、最後にクラスタを削除します。

>cfncluster delete  mycluster

starcluster と cfncluster その1

AWSのクーポンが5月末(つまり今日)で期限切れということに気付いたので、急遽starclusterとcfnclusterを触ってみることにしました。

STAR: Cluster - Home
CfnCluster

どちらも、pythonで書かれたAWS上でEC2のクラスタを構成するツールなんですが、前者はMITで開発されていて後者はAmazonが開発しているものです。
starclusterの方が古くからあったようで、githubの一番古いコミットは2009年のものでした。でもこの段階で既に動いてたっぽいので、プロジェクトの開始はもっと古そうです*1
一方のcfnclusterは20014年5月にプロジェクトを始めたようなので、約2年くらいの歴史ですね。

starclusterの特長はここのページにまとまってます。
What is StarCluster? — StarCluster 0.95.6 documentation
要するに、事前に色々とインストールしたAMIを用意してあって、任意のノード数のインスタンスを起動してセットアップしてくれるといったとこでしょうかね。

cfnclusterの方はもうちょっとインフラ寄りの機能しかなくて、インスタンスの起動とネットワーク構成あたりしかやらないようです。
要はソフトのインストールは、自分でAMIを用意してねというスタンスなんでしょうかね。
この辺のページを見てると、cloud watchやauto scalingとの連動のあたりは凝ったことやってるなーといったところですが、お手軽にクラウド上でHPCやりたいっていう層*2にはあんまり訴求しない気がします。
CfnCluster Processes — CfnCluster 1.2.1
あと、AWSのサービスを使いすぎてて、ベンダーロックイン感が高めですね。:p

インストール

とりあえず、両方ともインストールしてみましょう。なお、cfnclusterはpython2.7.10 on cygwin、starclusterはpython2.7.10 on windows7でやってます。cygwinで全部やるつもりだったんですが、starclusterのインストールに失敗したのでこっちだけnative環境でやり直しています。

starcluster

インストールしようとすると、pycryptoをビルドしようとして失敗するので、こちらのページを参考にVS90COMNTOOLSを上書きして無理矢理VS2015を使うように設定します。
「Unable to find vcvarsall.bat」の対処法 | Regen Techlog
違うバージョンのVSが入っている時や、そもそもVSなんぞ入れとらんという時は別の上記ページの別の方法で対処しましょう。

> python -m virtualenv --python=C:\Python27\python.exe starcluster
> cd starcluster
> Scripts\activate
> set VS90COMNTOOLS=%VS140COMNTOOLS%
> pip install starcluster
Collecting starcluster
Collecting iso8601>=0.1.8 (from starcluster)
  Using cached iso8601-0.1.11-py2.py3-none-any.whl
Collecting pycrypto>=2.5 (from starcluster)
  Using cached pycrypto-2.6.1.tar.gz
Collecting workerpool>=0.9.2 (from starcluster)
Collecting iptools>=0.6.1 (from starcluster)
  Using cached iptools-0.6.1-py2.py3-none-any.whl
Collecting scp>=0.7.1 (from starcluster)
  Using cached scp-0.10.2-py2.py3-none-any.whl
Collecting boto>=2.23.0 (from starcluster)
  Using cached boto-2.40.0-py2.py3-none-any.whl
Collecting Jinja2>=2.7 (from starcluster)
  Using cached Jinja2-2.8-py2.py3-none-any.whl
Collecting decorator>=3.4.0 (from starcluster)
  Using cached decorator-4.0.9-py2.py3-none-any.whl
Collecting paramiko>=1.12.1 (from starcluster)
  Using cached paramiko-2.0.0-py2.py3-none-any.whl
Collecting optcomplete>=1.2-devel (from starcluster)
Collecting six (from workerpool>=0.9.2->starcluster)
  Using cached six-1.10.0-py2.py3-none-any.whl
Collecting MarkupSafe (from Jinja2>=2.7->starcluster)
Collecting pyasn1>=0.1.7 (from paramiko>=1.12.1->starcluster)
  Using cached pyasn1-0.1.9-py2.py3-none-any.whl
Collecting cryptography>=1.1 (from paramiko>=1.12.1->starcluster)
  Using cached cryptography-1.3.2-cp27-none-win_amd64.whl
Requirement already satisfied (use --upgrade to upgrade): setuptools>=11.3 in c:\users\n_so5\onedrive\python\starcluster\lib\site-packages (from cryptography>=1.1->paramiko>=1.12.1->starcluster)
Collecting enum34 (from cryptography>=1.1->paramiko>=1.12.1->starcluster)
  Using cached enum34-1.1.6-py2-none-any.whl
Collecting ipaddress (from cryptography>=1.1->paramiko>=1.12.1->starcluster)
  Using cached ipaddress-1.0.16-py27-none-any.whl
Collecting idna>=2.0 (from cryptography>=1.1->paramiko>=1.12.1->starcluster)
  Using cached idna-2.1-py2.py3-none-any.whl
Collecting cffi>=1.4.1 (from cryptography>=1.1->paramiko>=1.12.1->starcluster)
  Using cached cffi-1.6.0-cp27-none-win_amd64.whl
Collecting pycparser (from cffi>=1.4.1->cryptography>=1.1->paramiko>=1.12.1->starcluster)
Building wheels for collected packages: pycrypto
  Running setup.py bdist_wheel for pycrypto ... done
  Stored in directory: C:\Users\n_so5\AppData\Local\pip\Cache\wheels\80\1f\94\f76e9746864f198eb0e304aeec319159fa41b082f61281ffce
Successfully built pycrypto
Installing collected packages: iso8601, pycrypto, six, workerpool, iptools, pyasn1, enum34, ipaddress, idna, pycparser, cffi, cryptography, paramiko, scp, boto, MarkupSafe, Jinja2, decorator, optcomplete, starcluster
Successfully installed Jinja2-2.8 MarkupSafe-0.23 boto-2.40.0 cffi-1.6.0 cryptography-1.3.2 decorator-4.0.9 enum34-1.1.6 idna-2.1 ipaddress-1.0.16 iptools-0.6.1 iso8601-0.1.11 optcomplete-1.2-devel paramiko-2.0.0 pyasn1-0.1.9 pycparser-2.14 pycrypto-2.6.1 scp-0.10.2 six-1.10.0 starcluster-0.95.6 workerpool-0.9.4 You are using pip version 8.0.2, however version 8.1.2 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

cfncluster

> python -m virtualenv cfncluster_cygwin
> cd cfncluster_cygwin/
> . bin/activate
> pip install cfncluster
Collecting cfncluster
  Downloading cfncluster-1.2.1.tar.gz
Collecting boto>=2.39 (from cfncluster)
  Downloading boto-2.40.0-py2.py3-none-any.whl (1.3MB)
    100% |████████████████████████████████| 1.4MB 660kB/s
Collecting awscli>=1.10.13 (from cfncluster)
  Downloading awscli-1.10.34-py2.py3-none-any.whl (938kB)
    100% |████████████████████████████████| 942kB 948kB/s
Collecting colorama<=0.3.3,>=0.2.5 (from awscli>=1.10.13->cfncluster)
  Downloading colorama-0.3.3.tar.gz
Collecting docutils>=0.10 (from awscli>=1.10.13->cfncluster)
  Downloading docutils-0.12.tar.gz (1.6MB)
    100% |████████████████████████████████| 1.6MB 465kB/s
Collecting rsa<=3.5.0,>=3.1.2 (from awscli>=1.10.13->cfncluster)
  Downloading rsa-3.4.2-py2.py3-none-any.whl (46kB)
    100% |████████████████████████████████| 51kB 1.9MB/s
Collecting botocore==1.4.24 (from awscli>=1.10.13->cfncluster)
  Downloading botocore-1.4.24-py2.py3-none-any.whl (2.3MB)
    100% |████████████████████████████████| 2.3MB 340kB/s
Collecting s3transfer==0.0.1 (from awscli>=1.10.13->cfncluster)
  Downloading s3transfer-0.0.1-py2.py3-none-any.whl
Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli>=1.10.13->cfncluster)
  Downloading pyasn1-0.1.9-py2.py3-none-any.whl
Collecting python-dateutil<3.0.0,>=2.1 (from botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Downloading python_dateutil-2.5.3-py2.py3-none-any.whl (201kB)
    100% |████████████████████████████████| 204kB 1.5MB/s
Collecting jmespath<1.0.0,>=0.7.1 (from botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Downloading jmespath-0.9.0-py2.py3-none-any.whl
Collecting futures<4.0.0,>=2.2.0; python_version == "2.6" or python_version == "2.7" (from s3transfer==0.0.1->awscli>=1.10.13->cfncluster)
  Downloading futures-3.0.5-py2-none-any.whl
Collecting six>=1.5 (from python-dateutil<3.0.0,>=2.1->botocore==1.4.24->awscli>=1.10.13->cfncluster)
  Downloading six-1.10.0-py2.py3-none-any.whl
Building wheels for collected packages: cfncluster, colorama, docutils
  Running setup.py bdist_wheel for cfncluster ... done
  Stored in directory: /home/n_so5/.cache/pip/wheels/26/c8/b0/3cf98bf7d72a9a63a358cbf094a50092641a70843de01ca155
  Running setup.py bdist_wheel for colorama ... done
  Stored in directory: /home/n_so5/.cache/pip/wheels/21/c5/cf/63fb92293f3ad402644ccaf882903cacdb8fe87c80b62c84df
  Running setup.py bdist_wheel for docutils ... done
  Stored in directory: /home/n_so5/.cache/pip/wheels/db/de/bd/b99b1e12d321fbc950766c58894c6576b1a73ae3131b29a151
Successfully built cfncluster colorama docutils
Installing collected packages: boto, colorama, docutils, pyasn1, rsa, six, python-dateutil, jmespath, botocore, futures, s3transfer, awscli, cfncluster
Successfully installed awscli-1.10.34 boto-2.40.0 botocore-1.4.24 cfncluster-1.2.1 colorama-0.3.3 docutils-0.12 futures-3.0.5 jmespath-0.9.0 pyasn1-0.1.9 python-dateutil-2.5.3 rsa-3.4.2 s3transfer-0.0.1 six-1.10.0

クラスタの起動

まずは、starclusterを使って4ノードのクラスタを作ってみましょう。
ここのチュートリアルを参考に、適当にいじっていきます。
Quick-Start — StarCluster 0.95.6 documentation

まずは、コンフィグファイルを生成します。

> starcluster help
Options:
--------
[1] Show the StarCluster config template
[2] Write config template to C:\Users\n_so5\.babun\cygwin\home\n_so5\.starcluster\config
[q] Quit
Please enter your selection: 2  <== 2を入力してテンプレートファイルを書き出させます。
>>> Config template written to C:\Users\n_so5\.babun\cygwin\home\n_so5\.starcluster\config
>>> Please customize the config template

続いて、生成されたconfigファイルを編集します。変更したのは以下の5行のみです。内部的にはbotoを使っているので、鍵関連は環境変数でも設定できるはずですが、設定ファイルを読み込んだ時点で値が入っていないとエラーチェックにひっかかるようです・・・

AWS_ACCESS_KEY_ID =     #your aws access key id here
AWS_SECRET_ACCESS_KEY = #your secret aws access key here
AWS_USER_ID =           #your 12-digit aws user id here
AWS_REGION_NAME =  ap-northeast-1
CLUSTER_SIZE = 4
NODE_INSTANCE_TYPE = c3.large

それから、keypairを生成します。

>starcluster createkey mykey -o %HOME%\.ssh\mykey.rsa

最後にクラスタを起動します。

>starcluster start smallcluster
StarCluster - (http://star.mit.edu/cluster) (v. 0.95.6)
Software Tools for Academics and Researchers (STAR)
Please submit bug reports to starcluster@mit.edu

>>> Using default cluster template: smallcluster
>>> Validating cluster template settings...
>>> Cluster template settings are valid
>>> Starting cluster...
>>> Launching a 4-node cluster...
>>> Creating security group @sc-smallcluster...
>>> Creating placement group @sc-smallcluster...
Reservation:r-cbaaa168
>>> Waiting for instances to propagate...
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Waiting for cluster to come up... (updating every 30s)
>>> Waiting for all nodes to be in a 'running' state...
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Waiting for SSH to come up on all nodes...
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Waiting for cluster to come up took 1.251 mins
>>> The master node is ec2-54-175-0-145.compute-1.amazonaws.com
>>> Configuring cluster...
>>> Running plugin starcluster.clustersetup.DefaultClusterSetup
>>> Configuring hostnames...
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Creating cluster user: sgeadmin (uid: 1001, gid: 1001)
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Configuring scratch space for user(s): sgeadmin
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Configuring /etc/hosts on each node
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Starting NFS server on master
>>> Configuring NFS exports path(s):
/home
>>> Mounting all NFS export path(s) on 3 worker node(s)
3/3 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Setting up NFS took 0.285 mins
>>> Configuring passwordless ssh for root
>>> Configuring passwordless ssh for sgeadmin
>>> Running plugin starcluster.plugins.sge.SGEPlugin
>>> Configuring SGE...
>>> Configuring NFS exports path(s):
/opt/sge6
>>> Mounting all NFS export path(s) on 3 worker node(s)
3/3 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Setting up NFS took 0.212 mins
>>> Installing Sun Grid Engine...
3/3 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Creating SGE parallel environment 'orte'
4/4 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 100%
>>> Adding parallel environment 'orte' to queue 'all.q'
>>> Configuring cluster took 2.328 mins
>>> Starting cluster took 3.701 mins

The cluster is now ready to use. To login to the master node
as root, run:

    $ starcluster sshmaster smallcluster

If you're having issues with the cluster you can reboot the
instances and completely reconfigure the cluster from
scratch using:

    $ starcluster restart smallcluster

When you're finished using the cluster and wish to terminate
it and stop paying for service:

    $ starcluster terminate smallcluster

Alternatively, if the cluster uses EBS instances, you can
use the 'stop' command to shutdown all nodes and put them
into a 'stopped' state preserving the EBS volumes backing
the nodes:

    $ starcluster stop smallcluster

WARNING: Any data stored in ephemeral storage (usually /mnt)
will be lost!

You can activate a 'stopped' cluster by passing the -x
option to the 'start' command:

    $ starcluster start -x smallcluster

This will start all 'stopped' nodes and reconfigure the
cluster.

ものの数分も待っていたら、クラスタの完成です!
さっそくログインしてみましょう。

>starcluster sshmaster smallcluster
StarCluster - (http://star.mit.edu/cluster) (v. 0.95.6)
Software Tools for Academics and Researchers (STAR)
Please submit bug reports to starcluster@mit.edu

>>> Starting Pure-Python SSH shell...
Line-buffered terminal emulation. Press F6 or ^Z to send EOF.

eval $(resize)
root@master:~# eval $(resize)
The program 'resize' is currently not installed. You can install it by typing:
apt-get install xterm

"Starting Pure-Python SSH shell"とか出てるので、どうやらこのためにParamikoを使っているようです。しかし、残念ながらtermcapだかterminfoだかの設定が入っていないのとwindowsコマンドプロンプト環境からだと激しく使い難い*3ので、事前に用意されているsgeadminというユーザのauthorized_keysに鍵を追加して後は普段から使っているsshクライアントを使って作業します。

> starcluster put smallcluster %HOME%\.ssh\id_rsa.pub ./
> starcluster sshmaster smallcluster
> root@master:~# cat id_rsa.pub >> ~sgeadmin/.ssh/authorized_keys
> starcluster listclusters
 StarCluster - (http://star.mit.edu/cluster) (v. 0.95.6)
Software Tools for Academics and Researchers (STAR)
Please submit bug reports to starcluster@mit.edu

-----------------------------------------------
smallcluster (security group: @sc-smallcluster)
-----------------------------------------------
Launch time: 2016-05-31 14:06:38
Uptime: 0 days, 00:23:07
VPC: vpc-9f9df4fa
Subnet: subnet-7907d752
Zone: us-east-1a
Keypair: mykey
EBS volumes: N/A
Cluster nodes:
     master running i-1a5d9286 ec2-54-175-0-145.compute-1.amazonaws.com
    node001 running i-1b5d9287 ec2-54-175-213-27.compute-1.amazonaws.com
    node002 running i-185d9284 ec2-54-89-100-190.compute-1.amazonaws.com
    node003 running i-195d9285 ec2-52-201-218-218.compute-1.amazonaws.com
Total nodes: 4

starcluster put {クラスタ名} でファイルをアップロード(getだと逆にダウンロード)できます。これで公開鍵を送りこんで、authorized_keysに末尾に追加しておきましょう。
terminalの設定がダメダメなのでコピペでなんとかするのはちょっと厳しげです。
あと、最後にやっているようにstarcluster listclustersコマンドを実行すると起動中のマシンのホスト名一覧が表示されるので、ここでmasterと表記されているノード(ec2-54-175-0-145.compute-1.amazonaws.com)へsshでログインします。
この時点でようやく気付いたんですが、REGION指定がうまく渡っていなかったようで、デフォルトのus-east-1にインスタンスが上がっていました・・・


続けてHPLでも流すかーと思ってたんですが、なんか設定が変なみたいで、mpiccはmpich2のものだけどmpirunはOpenMPIのものが使われているという謎な状況です。

sgeadmin@master:~$ which mpicc
/usr/bin/mpicc
sgeadmin@master:~$ which mpirun
/usr/bin/mpirun
sgeadmin@master:~$ file /usr/bin/mpicc /usr/bin/mpirun
/usr/bin/mpicc:  symbolic link to `/etc/alternatives/mpicc'
/usr/bin/mpirun: symbolic link to `/etc/alternatives/mpirun'
sgeadmin@master:~$ file /etc/alternatives/mpicc /etc/alternatives/mpirun
/etc/alternatives/mpicc:  symbolic link to `/usr/bin/mpicc.mpich2'
/etc/alternatives/mpirun: symbolic link to `/usr/bin/mpirun.openmpi'

alternativesって使ったことなかったんですが、ぐぐりながら状況を見てみるとこんな感じ。

> update-alternatives --display mpi
mpi - auto mode
  link currently points to /usr/include/mpich2
/usr/include/mpich2 - priority 40
  slave libmpi++.so: /usr/lib/libmpichcxx.so
  slave libmpi.so: /usr/lib/libmpich.so
  slave libmpif77.so: /usr/lib/libfmpich.so
  slave libmpif90.so: /usr/lib/libmpichf90.so
  slave mpic++: /usr/bin/mpic++.mpich2
  slave mpic++.1.gz: /usr/share/man/man1/mpic++.mpich2.1.gz
  slave mpicc: /usr/bin/mpicc.mpich2
  slave mpicc.1.gz: /usr/share/man/man1/mpicc.mpich2.1.gz
  slave mpicxx: /usr/bin/mpicxx.mpich2
  slave mpicxx.1.gz: /usr/share/man/man1/mpicxx.mpich2.1.gz
  slave mpif77: /usr/bin/mpif77.mpich2
  slave mpif77.1.gz: /usr/share/man/man1/mpif77.mpich2.1.gz
  slave mpif90: /usr/bin/mpif90.mpich2
  slave mpif90.1.gz: /usr/share/man/man1/mpif90.mpich2.1.gz
/usr/lib/openmpi/include - priority 40
  slave libmpi++.so: /usr/lib/openmpi/lib/libmpi_cxx.so
  slave libmpi.so: /usr/lib/openmpi/lib/libmpi.so
  slave libmpif77.so: /usr/lib/openmpi/lib/libmpi_f77.so
  slave libmpif90.so: /usr/lib/openmpi/lib/libmpi_f90.so
  slave mpiCC: /usr/bin/mpic++.openmpi
  slave mpiCC.1.gz: /usr/share/man/man1/mpiCC.openmpi.1.gz
  slave mpic++: /usr/bin/mpic++.openmpi
  slave mpic++.1.gz: /usr/share/man/man1/mpic++.openmpi.1.gz
  slave mpicc: /usr/bin/mpicc.openmpi
  slave mpicc.1.gz: /usr/share/man/man1/mpicc.openmpi.1.gz
  slave mpicxx: /usr/bin/mpic++.openmpi
  slave mpicxx.1.gz: /usr/share/man/man1/mpicxx.openmpi.1.gz
  slave mpif77: /usr/bin/mpif77.openmpi
  slave mpif77.1.gz: /usr/share/man/man1/mpif77.openmpi.1.gz
  slave mpif90: /usr/bin/mpif90.openmpi
  slave mpif90.1.gz: /usr/share/man/man1/mpif90.openmpi.1.gz
Current 'best' version is '/usr/include/mpich2'.

良くわからんけどrootで入り直して、マニュアルでOpenMPIに設定します。*4

# update-alternatives --config  mpi
There are 2 choices for the alternative mpi (providing /usr/include/mpi).

  Selection    Path                      Priority   Status
------------------------------------------------------------
* 0            /usr/include/mpich2        40        auto mode
  1            /usr/include/mpich2        40        manual mode
  2            /usr/lib/openmpi/include   40        manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/openmpi/include to provide /usr/include/mpi (mpi) in manual mode

もっかいsgeadminでログインしなおしてOpenMPIが使われるようになっているか確認します。

sgeadmin@master:~$ file /usr/bin/mpicc /usr/bin/mpirun
/usr/bin/mpicc:  symbolic link to `/etc/alternatives/mpicc'
/usr/bin/mpirun: symbolic link to `/etc/alternatives/mpirun'
sgeadmin@master:~$ file /etc/alternatives/mpicc /etc/alternatives/mpirun
/etc/alternatives/mpicc:  symbolic link to `/usr/bin/mpicc.openmpi'
/etc/alternatives/mpirun: symbolic link to `/usr/bin/mpirun.openmpi'

ようやく正常に使えるようになったので、こんな感じのテストプログラムを作って流してみます。

#include <mpi.h>
#include <stdio.h>

main(int argc, char** argv)
{
int nproc;
int myrank;
char hostname[80];
int name_len;
int ierr;
int i;
MPI_Init(&argc, &argv);

ierr=MPI_Comm_size(MPI_COMM_WORLD, &nproc);
if(ierr!=0) fprintf(stderr,"ierr from MPI_Comm_size = %d\n",ierr);
ierr= MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if(ierr!=0) fprintf(stderr,"ierr from MPI_Comm_rank = %d\n",ierr);

MPI_Get_processor_name(hostname, &name_len);
if(name_len >80) hostname[79]='\0';

for(i=0; i< nproc; i++)
{
  if(myrank==i)
  {
    fprintf(stderr,"myrank is %d of %d on %s\n",myrank,nproc, hostname);
  }
  MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
> mpicc tmp.c
> mpirun -np 8 -machinefile hostfile ./a.out
myrank is 0 of 8 on master
myrank is 1 of 8 on master
myrank is 2 of 8 on node001
myrank is 3 of 8 on node001
myrank is 4 of 8 on node002
myrank is 5 of 8 on node002
myrank is 6 of 8 on node003
myrank is 7 of 8 on node003

ようやく正常に流れました。ちなみ、alternativesの設定をいじるまではMPI_Comm_sizeを呼ぶとプロセス数が0だと言われていました。
mpich2とOpenMPIが混ざってたので、おそらくMPI_COMM_WORLDの値が両ライブラリの間で違うのが原因でしょう。

これは、複数のMPIライブラリが用意された環境だとはまるポイントで、MPIの規格で定義されているいくつかの値(MPI_COMM_WORLDとかMPI_SUMとか)は実はmpi.hの中で定義されているマクロ変数で実装されていることが多くて、なおかつライブラリが変われば値自体は異なるものになっていることが多いので互換性はありません。
これらの定義済変数はコンパイル時に(正確にはプリプロセス時に)それぞれのライブラリが定義した値へと置き換えられてしまうので、今回のようにコンパイル時に使ったmpi.hと実行時に呼ばれた共有ライブラリが別の実装のものになっていると、この値に不整合が発生し、呼び出し側ではMPI_COMM_WORLDを渡したつもりなのに、ライブラリ側では未定義のCOMMが指定されているという現象が起きます。*5
この辺の事情が分かっていないSEが適当な作業をすると、ユーザから「俺のプログラム動かんようになったやないか!」というクレームが飛んでくるので気をつけましょうw*6




さて、せっかくなのでHPLも流しときましょう。まずはHPLのソースをダウンロードしてきます。*7

HPL - A Portable Implementation of the High-Performance Linpack Benchmark for Distributed-Memory Computers

さっきの鍵と同じようにstarcluster putで送りこんで後はビルドして流すだけ。

> starcluster put smallcluster hpl-2.2.tar.gz /tmp
sgeadmin@master:~$ tar xfz /tmp/hpl-2.2.tar.gz
sgeadmin@master:~$ cd hpl-2.2/
sgeadmin@master:~/hpl-2.2$ cp setup/Make.Linux_PII_FBLAS ./

Make.Linux_PII_FBLASをエディタで開いて以下のように設定します。

TOPdir       = $(HOME)/hpl-2.2
MPdir, MPinc, MPlib  ->コメントアウト
LAdir=/usr/lib
Lalib= $(LAdir)/libblas.a
CC=mpicc
LINKER=mpicc

そして、make

> make arch=Linux_PII_FBLAS 2>&1 |tee makelog

正常にビルドできたら、bin/Linux_PII_FBLASの下にxhplという名前の実行ファイルとHPL.datという設定ファイルが生成されています。
デフォルトだとNsが小さすぎるのと、いくつかの設定を振りながら測定を繰り返す形になっているのでエディタでHPL.datを開いて"# of ~"と書かれている行の左端の数字を全部1にします。それから、Ns=10000, NBs=64, Ps=4, Qs=2くらいに設定してSGE経由でジョブを投げます。

> qsub -cwd -pe orte 8 -b y mpirun ./xhpl

正常に終了したらmpirun.o*とかmpirun.e*というファイルに標準出力や標準エラー出力が吐かれています。

sgeadmin@master:~/hpl-2.2/bin/Linux_PII_FBLAS$ cat mpirun.o13
================================================================================
HPLinpack 2.2  --  High-Performance Linpack benchmark  --   February 24, 2016
Written by A. Petitet and R. Clint Whaley,  Innovative Computing Laboratory, UTK
Modified by Piotr Luszczek, Innovative Computing Laboratory, UTK
Modified by Julien Langou, University of Colorado Denver
================================================================================

An explanation of the input/output parameters follows:
T/V    : Wall time / encoded variant.
N      : The order of the coefficient matrix A.
NB     : The partitioning blocking factor.
P      : The number of process rows.
Q      : The number of process columns.
Time   : Time in seconds to solve the linear system.
Gflops : Rate of execution for solving the linear system.

The following parameter values will be used:

N      :   10000
NB     :      64
PMAP   : Row-major process mapping
P      :       4
Q      :       2
PFACT  :    Left
NBMIN  :       2
NDIV   :       2
RFACT  :    Left
BCAST  :   1ring
DEPTH  :       0
SWAP   : Mix (threshold = 64)
L1     : transposed form
U      : transposed form
EQUIL  : yes
ALIGN  : 8 double precision words

--------------------------------------------------------------------------------

- The matrix A is randomly generated for each test.
- The following scaled residual check will be computed:
      ||Ax-b||_oo / ( eps * ( || x ||_oo * || A ||_oo + || b ||_oo ) * N )
- The relative machine precision (eps) is taken to be               1.110223e-16
- Computational tests pass if scaled residuals are less than                16.0

================================================================================
T/V                N    NB     P     Q               Time                 Gflops
--------------------------------------------------------------------------------
WR00L2L2       10000    64     4     2              88.81              7.509e+00
HPL_pdgesv() start time Tue May 31 07:56:39 2016

HPL_pdgesv() end time   Tue May 31 07:58:08 2016

--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)=        0.0013934 ...... PASSED
================================================================================

Finished      1 tests with the following results:
              1 tests completed and passed residual checks,
              0 tests completed and failed residual checks,
              0 tests skipped because of illegal input values.
--------------------------------------------------------------------------------

End of Tests.
================================================================================

8コアで7.6GFlopsってずいぶん低いですね。
使っているCPUは、 Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHzだそうなので、理論ピーク性能は8コア合計で 4*2*2.8*8= 172.7GFlopsなので実効効率は4.4%
さすがにサイズが小さすぎたようなので、N=40000まで増やして再測定してみました。しかし、これでも27.4GFlopsなので実効効率は15%くらいですかね。

================================================================================
T/V                N    NB     P     Q               Time                 Gflops
--------------------------------------------------------------------------------
WR00L2L2       40000    64     4     2            1557.25              2.740e+01
HPL_pdgesv() start time Tue May 31 08:17:37 2016

HPL_pdgesv() end time   Tue May 31 08:43:35 2016

--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)=        0.0007106 ...... PASSED
================================================================================

ドキュメントによれば、starclusterが使っているBLASはAtlasらしいので、リビルドしていない状態だとこんなもんで限界かもしれません。時間があったら、HPCCのDGEMMテストでも使って追試してみましょう。


かなり長くなってしまったので、cfnclusterは次の記事に分けます。

*1:2008年のSCの時に見たような気がするけど、気のせいかも

*2:そんな層が居るかどうかはともかくとしてw

*3:Ctrol-C押すといきなりsshのセッションが切れたりとか・・・

*4:これ、本来はauto設定にするならpriorityの値を変えないと駄目なんじゃなかろうか・・・

*5:Commが未定義の時にMPI_Comm_size/rankがこんな挙動してて良いのかどうかは未確認

*6:といいつつ、MPI関連とかジョブスケジューラ関連の設定ミスはエンドユーザから指摘してもなかなか理解していないSEが多いのも事実。

*7:あら、今年に入ってアップデートされてるな・・・今さら何を変えたんだろうか。

windows(cygwin)でansibleその3

とりあえずparamikoで動くようになったものの、.ssh/configが使えないという致命的な欠点に気付いて、再トライしてみました。

といっても、ぐぐれどもぐぐれども前々回みつけたこのblogと同じく、"-o ContorolMaster=no"を指定すればOKって記事しかひっかかりません。
blog.simonmetzger.de


駄目もとでもう一回やってみようかと思って、ansible.cfgに

[ssh_connection]
ssh_args = -o ControlMaster=no

を書くと・・・あっさり成功しました。

しかも、何回か間隔を空けて再実行してみましたが100%成功してます。



改めて前々回の自分の記事を見直すと

しかし、ansible.cfgに書いたのでは-vvvvオプションを付けると、あいかわらずControlMaster=autoになっていたので、コマンドライン引数を追加して

> ansible hoge.huga.com -m ping -i hosts --ssh-extra-args="-o ControlMaster=no"

にしてみました。

とあります。しかし、これが何かの間違いだったようで*1今回は-vvvvオプションを付けたら、ControlMaster=noが設定されていました。
おそらく、ansible.cfgに書くとデフォルトで付けるオプションを変更するけど、--ssh-extra-argsだと追加で渡すという挙動なんじゃないかと思います。*2

というわけで、前回作ったparamikoの設定は破棄してOpenSSHとともに生きていきます。

*1:ansible.cfgのスペルを間違えてたとか、そんなレベルの単純ミスな気がする・・・

*2:名前的にもssh_argsとssh-extra-argsだから、この挙動の方が正しそう

windows(cygwin)でansibleその2

ssh接続に成功したりしなかったりする問題は結局解決しないままなんですが、

OpenSSHがだめならparamikoを使えば良いじゃない

ということで、paramikoで試してみました。


ansible hoge.huga.com -m ping -i hosts -c paramiko -k
SSH password:  <- 秘密鍵のパスフレーズを入力
hoge.huga.com | SUCCESS => {
    "changed": false,
    "ping": "pong"
}


こっちはあっさり成功!
何回か試しましたが、100%つながります。

ただし、ここの記事によると、paramikoを使うとOpenSSHより遅いらしいので、ansible.cfgに

RHEL6系でansibleを使うならrecord_host_keysをFalseにすると速くなる - still deeper

record_host_keys=False

を指定しておきます。あと-c paramikoとかも毎回指定するのも面倒なので、まとめてansible.cfgには次のように指定しておきます。

[defaults]
ask_pass=True
transport=paramiko
[paramiko]
record_host_keys=False

これでもっかいpingを打ってみると

ansible hoge.huga.com -m ping -i hosts -c paramiko -k
SSH password:  <- 秘密鍵のパスフレーズを入力
hoge.huga.com | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

うむ。問題無し
パフォーマンスを考えると、そのうちparamikoからOpenSSHに乗り換えたくなるかもしれませんが、そんな大規模ノードの管理に使うつもりは無いので当面はこれでやってみます。

windows(cygwin)でansible

ずいぶん前に、windows nativeなpythonに無理矢理ansibleをインストールしてみたら、pwdだのfcntlだのといったUnix固有の標準ライブラリに依存しまくってて、まったく歯が立たなかったので放置してたんですが、最近babunというcygwinの派生版を使い始めたのでこっちで試してみることにしました。

pipのインストール

現時点のbabunのpythonは2.7.10なので、pipのwebページによるとインストール済のはずですが、

pip is already installed if you're using Python 2 >=2.7.9 or Python 3 >=3.4 downloaded from

https://pip.pypa.io/en/stable/installing/

どうやらインストールされてないようでwhich pipするとwindows nativeのpython用のpipが返されます。

> which pip
/cygdrive/c/ProgramData/chocolatey/bin/pip


公式ページの英語版ドキュメントによると

The ensurepip package provides support for bootstrapping the pip installer into an existing Python installation or virtual environment. This bootstrapping approach reflects the fact that pip is an independent project with its own release cycle, and the latest available stable version is bundled with maintenance and feature releases of the CPython reference interpreter.

In most cases, end users of Python shouldn’t need to invoke this module directly (as pip should be bootstrapped by default), but it may be needed if installing pip was skipped when installing Python (or when creating a virtual environment) or after explicitly uninstalling pip.

https://docs.python.org/2.7/library/ensurepip.html

とのことなので、ensurepipを使ってインストールしましょう。

> which python
/usr/bin/python
> python -m ensurepip
Ignoring indexes: https://pypi.python.org/simple
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Successfully installed pip-6.1.1 setuptools-15.2
> which pip
/usr/bin/pip
> pip install -U pip
You are using pip version 6.1.1, however version 8.1.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting pip
  Downloading pip-8.1.0-py2.py3-none-any.whl (1.2MB)
    100% |████████████████████████████████| 1.2MB 327kB/s
Installing collected packages: pip
  Found existing installation: pip 6.1.1
    Uninstalling pip-6.1.1:
      Successfully uninstalled pip-6.1.1
Successfully installed pip-8.1.0

virtualenvのインストール

以前書いたwindows版の記事を参考にpipでインストールします。
hpcmemo.hatenablog.com

> pip install virtualenv
Collecting virtualenv
  Downloading virtualenv-15.0.0-py2.py3-none-any.whl (1.8MB)
    100% |████████████████████████████████| 1.8MB 231kB/s
Installing collected packages: virtualenv
Successfully installed virtualenv-15.0.0

ansibleのインストール

virtualenvで環境を作って、ansibleをインストールします。

> virtualenv ansible
New python executable in /cygdrive/c/Users/n_so5/OneDrive/Python/ansible/bin/python2.7
Also creating executable in /cygdrive/c/Users/n_so5/OneDrive/Python/ansible/bin/python
Installing setuptools, pip, wheel...done.
> cd ansible
> . bin/activate
(ansible)>  pip install ansible
Collecting ansible
  Using cached ansible-2.0.1.0.tar.gz
Collecting paramiko (from ansible)
  Downloading paramiko-1.16.0-py2.py3-none-any.whl (169kB)
    100% |████████████████████████████████| 174kB 706kB/s
Collecting jinja2 (from ansible)
  Downloading Jinja2-2.8-py2.py3-none-any.whl (263kB)
    100% |████████████████████████████████| 266kB 1.1MB/s
Collecting PyYAML (from ansible)
  Downloading PyYAML-3.11.tar.gz (248kB)
    100% |████████████████████████████████| 256kB 758kB/s
Requirement already satisfied (use --upgrade to upgrade): setuptools in /usr/lib/python2.7/site-packages (from ansible)
Collecting pycrypto>=2.6 (from ansible)
  Downloading pycrypto-2.6.1.tar.gz (446kB)
    100% |████████████████████████████████| 450kB 975kB/s
Collecting ecdsa>=0.11 (from paramiko->ansible)
  Downloading ecdsa-0.13-py2.py3-none-any.whl (86kB)
    100% |████████████████████████████████| 92kB 2.3MB/s
Collecting MarkupSafe (from jinja2->ansible)
  Downloading MarkupSafe-0.23.tar.gz
Installing collected packages: ecdsa, pycrypto, paramiko, MarkupSafe, jinja2, PyYAML, ansible
  Running setup.py install for pycrypto ... done
  Running setup.py install for MarkupSafe ... done
  Running setup.py install for PyYAML ... done
  Running setup.py install for ansible ... done
Successfully installed MarkupSafe-0.23 PyYAML-3.11 ansible-2.0.1.0 ecdsa-0.13 jinja2-2.8 paramiko-1.16.0 pycrypto-2.6.1

動作確認

とりあえずテストとしてpingでも打ってみます。

> echo hoge.huga.com > hosts
> ansible hoge.huga.com -m ping -i hosts
0 [main] python2.7 6852 child_info_fork::abort: address space needed by '_speedups.dll' (0x460000) is already occupied
ERROR! Unexpected Exception: 'NoneType' object has no attribute 'terminate'
to see the full traceback, use -vvv

_sppedups.dllってなんじゃと思ってfindしてみると

> find ./ -name _speedups.dll
./lib/python2.7/site-packages/markupsafe/_speedups.dll

さっきansibleを入れた時に一緒にインストールされたMarkupSafeに含まれるライブラリのようです。

おそらく、こちらの記事と同じ問題だろうと推測して、同じことをやってみます。
d.hatena.ne.jp

> find `pwd` -name '*.dll' -o -name '*.so' >~/rebase_list
一旦babunのターミナルを終了して、%USERPROFILE%\.babun\cygwin\bin\ash.exe を実行
$cd $HOME
$/bin/rebaseall -T rebase_list -v
(中略)
/usr/bin/cygattr-1.dll: new base = 6fe10000, new size = 10000
/usr/bin/cygatomic-1.dll: new base = 6fe20000, new size = 20000
/usr/bin/cygaspell-15.dll: new base = 6fe40000, new size = b0000
/usr/bin/cygarchive-13.dll: new base = 6fef0000, new size = b0000
/usr/bin/cygaprutil-1-0.dll: new base = 6ffa0000, new size = 30000
/usr/bin/cygapr-1-0.dll: new base = 6ffd0000, new size = 30000

再度babunを起動して、

> ansible hoge.huga.com -m ping -i hosts
hoge.huga.com | UNREACHABLE! => {
    "changed": false,
    "msg": "SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue",
    "unreachable": true
}

forkの問題は解消されたっぽいけどやっぱり接続できません。
とりあえず、-vvvvを付けて実行してみると、ログの最後の方で"Broken Pipe"というのが表示されていたのでぐぐってみたところ、こんな記事がひっかかりました。
blog.simonmetzger.de
しかし、ansible.cfgに書いたのでは-vvvvオプションを付けると、あいかわらずControlMaster=autoになっていたので、コマンドライン引数を追加して

> ansible hoge.huga.com -m ping -i hosts --ssh-extra-args="-o ControlMaster=no"

にしてみました。

それでもUNREACHABLEは変わらないので、さらにしばらくぐぐり続けたところ、こんなページがみつかりました。
serverfault.com
.sshの下のファイルのowner/groupを見たらgroupが"None"になっていたので、試しに

> chown ユーザ名:Users ~/.ssh/*

をしてみたところ、ようやく接続できました。

> ansible hoge.huga.com -m ping -i hosts --ssh-extra-args="-o ControlMaster=no"
hoge.huga.com | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

何回か再実行すると、時々FAILになったりするので、ちょっと実用にはほど遠いんですがとりあえずこの辺で一旦終了しときます。

これまでのまとめ

babun環境からansibleを使う時は

  • ansibleをインストールしたら、dllファイルのリストを作ってrebaseall
  • .ssh/ 以下のファイルのowner/groupを正しく設定する
  • --ssh-extra-args="-o ControlMaster=no"をつける

それでも、なんか失敗する時あり・・・orz