mod_wsgi とライブラリ読み込み
先日行った、Caffe で推論処理を行う API サーバーの移行時に発生したエラーとその対処法シリーズの第三弾です。
関連エントリーは以下の通りです。
- 元の Caffe サーバー構築記事
- 第一弾: mod_wsgi インストール中に gcc failed | もばらぶエンジニアブログ
- 第二弾: mod_wsgi + Anaconda で undefined symbol: SSLv2_method | もばらぶエンジニアブログ
(移行後の)環境
第一弾・第二弾で記載した内容を再掲します。
- AWS Deep Learning AMI (Ubuntu、移行前は Amazon Linux 版の DL AMI)
- その他の環境は変わらず
caffe_p27
環境- Apache 2.4
- etc.
- AWS Deep Learning AMI (Ubuntu、移行前は Amazon Linux 版の DL AMI)
- その他の環境は変わらず
caffe_p27
環境- Apache 2.4
- etc.
エラーとその原因
[Sun Jan 27 16:39:56.540744 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] mod_wsgi (pid=13877): Failed to exec Python script file '/var/www/foo-caffe-api/foo-caffe-api.wsgi'.
[Sun Jan 27 16:39:56.540783 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] mod_wsgi (pid=13877): Exception occurred processing WSGI script '/var/www/foo-caffe-api/foo-caffe-api.wsgi'.
[Sun Jan 27 16:39:56.540811 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] Traceback (most recent call last):
[Sun Jan 27 16:39:56.540829 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] File "/var/www/foo-caffe-api/foo-caffe-api.wsgi", line 10, in <module>
[Sun Jan 27 16:39:56.540887 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] from api_server import app as application
[Sun Jan 27 16:39:56.540908 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] File "/var/www/foo-caffe-api/api_server.py", line 42, in <module>
[Sun Jan 27 16:39:56.540966 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] import caffe
[Sun Jan 27 16:39:56.540976 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] File "/home/ubuntu/src/caffe_python_2/python/caffe/__init__.py", line 1, in <module>
[Sun Jan 27 16:39:56.541009 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] from .pycaffe import Net, SGDSolver, NesterovSolver, AdaGradSolver, RMSPropSolver, AdaDeltaSolver, AdamSolver, NCCL, Timer
[Sun Jan 27 16:39:56.541019 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] File "/home/ubuntu/src/caffe_python_2/python/caffe/pycaffe.py", line 13, in <module>
[Sun Jan 27 16:39:56.541125 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] from ._caffe import Net, SGDSolver, NesterovSolver, AdaGradSolver, \\
[Sun Jan 27 16:39:56.541144 2019] [wsgi:error] [pid 13877] [remote 127.0.0.1:41856] ImportError: libnccl.so.2: cannot open shared object file: No such file or directory
*.wsgi, *.py を配置して、wsgi の設定をした後、Apache を再起動して API サーバーにアクセスすると、上のようなエラーが出ました。エラーメッセージの末尾に記載されているように、*.so が読み込まれていないのが原因です。ちなみに、同 so ファイルは、find
コマンドで存在することは確認済みです。
mod_wsgi とその実行環境の設定
mod_wsgi で動く Python アプリケーションで、(ライブラリ読み込みのための)LD_LIBRARY_PATH
や、その他環境変数を設定したいというのは割と良くある話題のようです。mod_wsgi の作者である Graham さんも、以下のような gist を作って、いくつかの方法を紹介しています。
Setting environment variables for Apache/mod_wsgi hosted Python application.
大雑把にまとめると、mod_wsgi で環境を設定する方法は主に
- *.wsgi ファイルで、
os.environ
を使って環境変数を設定する- その派生形で、*.wsgi から別の *.py ファイルを呼び出し、
os.environ
で設定する
- その派生形で、*.wsgi から別の *.py ファイルを呼び出し、
- Apache の設定ファイルで、
python-path
かpython-home
を設定する - ライブラリ関連は、上の2つの方法ではダメなので、python モジュールインストール時に
LD_RUN_PATH
を設定する(LD_LIBRARY_PATH
は設定不要)
の三通りとなります。
ライブラリ関連の場合、なぜ最初の2つの方法だとダメかという理由ですが、LD_LIBRARY_PATH
の読み込み・ライブラリ読み込みは、プロセス起動時に一度だけ行われるからなので、プロセス起動後に設定はできません。
では、ライブラリ読み込みの問題は三番目の方法で解決するかというと、そうではありません。この方法は、既にモジュールがインストール済みの場合には使えないので、別の方法を選択する必要があります。
対処法: LD_LIBRARY_PATH を設定
結論としては、第二弾で書いた通りですが、以下に再掲します。
/etc/apache2/envvars
で適切な LD_LIBRARY_PATH
を設定して、Apache を再起動すれば良いです。
設定すべき LD_LIBRARY_PATH
を調べるには、以下のようにします。
ubuntu@ip-nnn-nnn-nnn-nnn:~$ source activate caffe_p27
(caffe_p27) ubuntu@ip-nnn-nnn-nnn-nnn:~$ printenv LD_LIBRARY_PATH
/usr/local/cuda-8.0/lib64:/usr/local/cuda-8.0/extras/CUPTI/lib64:/lib/nccl/cuda-8.0/lib:/usr/lib64/openmpi/lib/:/usr/local/lib:/usr/lib:/usr/local/mpi/lib:/lib/:/usr/lib64/openmpi/lib/:/usr/local/lib:/usr/lib:/usr/local/mpi/lib:/lib/::/home/ubuntu/anaconda3/envs/caffe_p27/lib/
envvars ファイルには、以下のような行を追加します。
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:/usr/local/cuda-8.0/extras/CUPTI/lib64:/lib/nccl/cuda-8.0/lib:/usr/lib64/openmpi/lib/:/usr/local/lib:/usr/lib:/usr/local/mpi/lib:/lib/:/usr/lib64/openmpi/lib/:/usr/local/lib:/usr/lib:/usr/local/mpi/lib:/lib/::/home/ubuntu/anaconda3/envs/caffe_p27/lib/
なお、これも前回書いた通りですが、AWS DL AMI のバージョンによって、 LD_LIBRARY_PATH
の値は若干異なります。
その他の方法
読み込む so ファイルが1つだけであれば、Apache のLoadFile
でも大丈夫そうです。
python – How to set LD_LIBRARY_PATH for apache+wsgi website – Stack Overflow
ただ、今回は、Anaconda 環境の so ファイルを色々と読み込む必要があるので、 LD_LIBRARY_PATH
を設定するのが一番簡単な選択肢だと思います。
まとめ
今回で、エラー対処シリーズ三部作は完了です。mod_wsgi は色々と面倒くさかったので(勉強にはなりましたが)、次にサーバーを立てるときには、スタンドアロンサーバーを立てようと思います。
コメントを残す