さくらレンタルサーバーにgcc、Python3、numpy、scipy、scikit-learn、gensimをインストールする

さくらレンタルサーバーに、Python3.6と、numpy、scipy、scikit-learn、gensimなどのPythonモジュールをインストールした模様をレポートします。

これらのインストールの前に、必要なgcc、gfortranのインストールからレポートを始めます。

はじめに

機械学習の結果のCGIを動かす環境が必要になりました。Python3の、scikit-learn、gensimを使ったCGIです。

VPSを借りれば良いのでしょうが、とりあえずさくらレンタルサーバーでやってみようと。

gensimにはnumpy、scipyが必要。numpy、scipy、scikit-learnには代数演算ライブラリ(ATLASなどのBLAS, LAPACK)が必要。

そして代数演算ライブラリのビルドにはFortranが必要。

さくらレンタルサーバーにはgccはあるけどgfortranは入っていない。Python2.7は入っているけどPython3は入っていない。

ということでアップデートも兼ねてgccからインストールしよう!

後悔先に立たず。

良い子はマネしちゃダメ。

以下のレポートについて

本稿はさくらレンタルサーバーに特化した、FreeBSD、管理者権限なしでのインストールのレポートです。(Linuxだったり管理者権限があったりする場合はもっと簡単なことでしょう。)

FreeBSDへのLinux等のパッケージのビルドはPortsを利用するのが正統なようです。しかしレンタルサーバーにPortsは入っていないでしょうし、管理者権限もありません。

それでも以下のように必要なもののビルドは可能でした。しかし実行時に何かしらエラーはでるかもしれません。

もし追試しようと思われている方は、一度長文(5000文字超)を通し読みして頂いたほうがよろしいかと思います。その上で自己責任にてお願いします。

試行錯誤の連続でしたので、正確に記録していません。記述間違いはあると思いますので、各位の経験で補正してください。

パッケージ名は作業ディレクトリに残っているのを見ればわかるのですが、ダウンロードURLは記録していません。検索してお探しください。(ほぼGNUのサイトですが。)

そしてインストールするツールやモジュールのバージョンが異なると、このレポートとは異なるエラーも出ることでしょう。

また、ビルドはレンタルサーバーのCPUリソースが必要でしょうから、極力しないことをおすすめします。(自分のことは棚に上げて。)

事前準備

ユーザーディレクトリ直下にlocalを作成して、インストールは全てここにすることにします。作業用にtmpディレクトリも作ります。
また.cshrcもあらかじめ編集しておきます。

mkdir ~/local
mkdir ~/tmp
cp .cshrc .cshrc.bak
vi .cshrc

set pathの最初に「$HOME/local/bin」を追加し、以降に環境変数の設定を追加します。

set path = ($HOME/local/bin /sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin )

setenv PYTHON $HOME/local
setenv PYTHONPATH $HOME/local/lib/python3.6/site-packages 
setenv C_INCLUDE_PATH $HOME/local/include 
setenv CPLUSE_INCLUDE_PATH $HOME/local/include 
setenv LIBRARY_PATH $HOME/local/lib
setenv LD_LIBRARY_PATH $HOME/local/lib

上の記述は十分で無いかもしれませんが、この内容で以下のレポート内容は可能でした。

 

以降、一つ一つのイントールが完了するたびに以下を行い、直後からツールが使えるようにして作業ディレクトリにもどります。

source ~/.cshrc
cd ~/tmp

これらの記述は、以降省略します。

慣れている方にとっては当たり前ですが、そうでない方はお忘れなく~。

GNUツールのビルドとインストール

まずはGNUのツールからインストールします。

gccに必要なツールのインストール

インストール方法は、凡そ以下です。

wget <URL>
tar xf <パッケージのアーカイブ>
cd <展開先>
./configure prefix=$HOME/local
make
make install

インストールしたパッケージは以下です。

  • gmp-5.1.3.tar.xz
  • mpfr-3.1.5.tar.xz
  • mpc-1.0.2.tar.gz
  • make-3.82.tar.gz
  • binutils-2.29.tar.gz

gccのインストールに必須なのは最初の3つ。gmpは6系だとm4がないとかエラーがでました。

既存のmakeはFreeBSDのものなので、理解できない変数があるとエラーが出がち。GNU makeも入れてしまえ。しかし既存のmakeでビルドできるのは、ちょっと古い上のバージョン。(一回入れてしまえば、それで新しいのも入るかも。)

binutilsも入れておきます。

gccのインストール

パッケージはgcc-6.4.0.tar.gzです。

wgetしてtar xfの後から…

cd gcc-6.4.0
mkdir build
cd build
../configure --prefix=$HOME/local --enable-languages=c,c++,fortran --disable-bootstrap CFLAGS="-I$HOME/local/include" CPPFLAGS="-I$HOME/local/include" CXXFLAGS="-I$HOME/local/include" LDFLAGS="-L$HOME/local/lib" CFLAGS_FOR_TARGET="-I$HOME/local/include" CPPFLAGS_FOR_TARGET="-I$HOME/local/include" CXXFLAGS_FOR_TARGET="-I$HOME/local/include" LDFLAGS_FOR_TARGET="-L$HOME/local/lib"
make
make install

4行のconfigure:

../configure --prefix=$HOME/local --enable-languages=c,c++,fortran --disable-bootstrap CFLAGS="-I$HOME/local/include" CPPFLAGS="-I$HOME/local/include" CXXFLAGS="-I$HOME/local/include" LDFLAGS="-L$HOME/local/lib" CFLAGS_FOR_TARGET="-I$HOME/local/include" CPPFLAGS_FOR_TARGET="-I$HOME/local/include" CXXFLAGS_FOR_TARGET="-I$HOME/local/include" LDFLAGS_FOR_TARGET="-L$HOME/local/lib"

ですが、~FLAGS_FOR_TARGETも設定してあげないとエラーになりました。環境変数に適切に設定すれば必要ないのかもしれませんが、試行錯誤の結果がこの形です。

あと最初は--enable-languagesを指定していませんでしたが、javaのライブラリのビルドでエラーがでるので、fortranまでの指定にしました。

sourceの後、--versionを指定するなどして、gcc, gfortranが使えることを確認します。

Python3のインストールとCGIテスト

続いてPython3をインストールします。

Python3.6のインストール

Python-3.6.2.tgzのwget、tar xfの後から、

cd Python-3.6.2
./configure --prefix=$HOME/local
make
make install

sourceの後にpython3とpip3が使えることを確認します。

以降pythonと打ってしまうと、/usr以下の2.7が動くのでご要注意を。

CGIのテスト環境の作成

次々章に書きますPythonモジュールのインストールにおいて、CGIの実行時ではじめてエラーがでる、という場合が多々ありました。

最初にCGIのテスト環境を作っておき、逐次CGIでの確認を行う方が効率良いです。

HTTPでアクセスできるそのテスト環境を「~/www/test」とします。

mkdir ~/www/test
chmod 755 ~/www/test

そして以下の2つのファイルを作成し、FTPなどでこのディレクトリにアップロードします。(さくらレンタルサーバーは拡張子が.cgiの場合は.htaccessはいらないかも。)

.htaccess

AddHandler cgi-script .cgi

test.cgi

#!/home/your-site/local/bin/python3
import os, sys, platform

def import_check(name):
    print("")
    try:
        mod = __import__(name)
        if name=="numpy" or name=="scipy":
            print("%s config:" % name)
            mod.show_config()
        print("Success to import %s." % name)
    except:
        print(sys.exc_info())
        print("Fail to import %s." % name)
        sys.exit(1)

print("Content-type: text/plain")
print("")
print("Python %s" % platform.python_version())

modules = ["numpy", "scipy", "sklearn", "gensim", ]
for mod in modules:
    import_check(mod)

print("Success to import all.")

1行の「/home/your-site/」はユーザーディレクトリです。各位の環境に読み替えて下さい。(以下同様)

そして少なくとも、この行の改行コードはLFでないと動きません。(CRLFでも後ろに記号を付けるという回避策があったかと思いますが忘れました。)

コンソールに戻りパーミッションを変えます。

chmod 755 ~/www/test/test.cgi
~/www/test/test.cgi

2行でtest.cgiを実行し、「Python 3.6.2」のように表示されることを確認します。(numpyはまだインストールしていないのでFail。)

そしてブラウザからtest.cgiにアクセスし、同様に表示されれば成功です。

もし500エラーが出る場合は、各ファイルの内容、改行コード、パーミッションを確認してみてください。

Pythonモジュールのインストールの準備

Pythonモジュールのインストールの前に、幾つか準備が必要です。

numpy,scipy,scikit-learnが参照する代数演算ライブラリからインストールします。(ここからURLもメモしてあります。)

ATLASのインストール

代数演算ライブラリのATLASをLAPACK付きでインストールします。このビルドにFortranが必要です。

http://www.netlib.org/lapack/ からlapack-3.7.1.tgzを、https://sourceforge.net/projects/math-atlas/ からatlas.3.10.3.tar.bz2をダウンロードします。

wget http://www.netlib.org/lapack/lapack-3.7.1.tgz
wget https://downloads.sourceforge.net/project/math-atlas/Stable/3.10.3/atlas3.10.3.tar.bz2
tar xf atlas3.10.3.tar.bz2
cd ATLAS
mkdir build
cd build
../configure -b 64 -C ic gcc -F ic -O3 -C if gfortran -F if -O3 --prefix=$HOME/local --shared --with-netlib-lapack-tarfile=$HOME/tmp/lapack-3.7.1.tgz  
make
make install

7行のconfigure:

../configure -b 64 -C ic gcc -F ic -O3 -C if gfortran -F if -O3 --prefix=$HOME/local --shared --with-netlib-lapack-tarfile=$HOME/tmp/lapack-3.7.1.tgz  

のオプションは、展開後ディレクトリのdoc/atlas_install.pdfを参考にしました。

make installでエラーが出ますが、dllとかdylibとか必要ない拡張子のファイルのコピーの失敗なので気にしないことにします。

ATLASの追加インストール

上のATLASでnumpyをインストールした時に、CGIにて「import numpy」の実行時に「libtatlas.soが参照するlibgfortran.soが見つからないよ。再インストールし直せ」というエラーが発生しました。(sshから叩くと発生しません。)

そこで以下のように、libtatlas.soをビルドし直したところ、CGIでのエラーは消えました。

cd ~/tmp/ATLAS/build
cp -r lib xlib
cd xlib
gcc -fomit-frame-pointer -mfpmath=sse -O2 -fno-schedule-insns2 -mavx -m64 -fPIC -shared -o libtatlas.so -Wl,-rpath $HOME/local/lib -Wl,--whole-archive libptlapack.a libptf77blas.a libptcblas.a libatlas.a -Wl,--no-whole-archive -L$HOME/local/lib -lgfortran -lc -lpthread -lm –lgcc
cp libtatlas.so ~/local/lib

4行のリンクのコマンドライン:

gcc -fomit-frame-pointer -mfpmath=sse -O2 -fno-schedule-insns2 -mavx -m64 -fPIC -shared -o libtatlas.so -Wl,-rpath $HOME/local/lib -Wl,--whole-archive libptlapack.a libptf77blas.a libptcblas.a libatlas.a -Wl,--no-whole-archive -L$HOME/local/lib -lgfortran -lc -lpthread -lm –lgcc

に関して、makeでは「-Wl, -rpath-link」で$HOME/local/libを設定していましたが、上では「-Wl,-rpath」にしています。-rpath-linkでもよいように思うのですがね。(今見るとスペースのせいでしょうか。makeではダブルクォーテーションがあり、このコマンドラインは失敗していました。)

もう一つのlibsatlas.soも一応リンクし直しておきます。

gcc -fomit-frame-pointer -mfpmath=sse -O2 -fno-schedule-insns2 -mavx -m64 -fPIC -shared -o libsatlas.so -Wl,-rpath $HOME/local/lib -Wl,--whole-archive liblapack.a libf77blas.a libcblas.a libatlas.a -Wl,--no-whole-archive -L$HOME/local/lib -lgfortran -lc -lpthread -lm -lgcc
cp libsatlas.so ~/local/lib

CGIでの実行時にLD_LIBRARY_PATHが有効になるやり方があれば、この工程は必要ないのでしょう。

モジュールのエラー

Pythonモジュールを普通にインストールしたとき、sshから手で叩くと実行できるのにCGI経由だとエラーがでるケースがありました。

それらのエラーは、前節のATLASと同様「共有ライブラリ(so)からさらに共有ライブラリを呼ぶときに見つからない」というものです。

LD_LIBRARY_PATHDT_RUNPATHの類の環境変数を設定すれば良いかと思いましたが、さくらレンタルサーバーのsuexec経由では.htaccessでのSetEnvが効きません。

sitecustomize.pyを作成して、そこで「import os; os.environ["LD_LIBRARY_PATH"] = "/home/your-site/local/lib"」とかやってもエラーは消えませんでした。

シェルスクリプト等で環境変数を設定する踏台CGIを作るという手も考えられますが、その度に踏台を作るのも面倒です。

ここでの解決策は「rpathを指定してビルドする」という面倒なものです。もしライブラリパスが設定できる解決策がありましたら、そちらのほうが楽です。

(リンカ―のrpathオプションは、オブジェクトが共有ライブラリを探すときのパスをそのオブジェクト自身に書き込む、というものです。)

pip.confの作成

rpathの指定はpipのオプションで指定できます。たぶん以下のような感じ。(試していません。)

pip3 install numpy --global-option=build_ext --global-option=-R/home/your-site/local/lib

しかし今後、soを作るかもしれないモジュールをインストールする度にオプションを指定するのも面倒です。そしてきっと忘れますので、ここでpip.confを作っておきます。(もしpython2にもpipを入れていましたら、そちらのpipも同じpip.confを参照するかもしれませんのでご注意ください。)

mkdir ~/.pip
vi ~/.pip/pip.conf

pip.confの内容は次の2行です。

[install]
global-option = build_ext --rpath=/home/your-site/local/lib

setup.pyのbuild_extコマンド実行で--rpathを指定しています。

(もしかしたら「global-option = build_ext --rpath=/home/your-site/local/lib:/usr/lib:/lib」などのほうが良かったかもしれませんが、.cshrcのLD_LIBRARY_PATHも前述の通りだからまいっか。パスの区切りがコロンで良いかは調べていません。)

参考:


前節のようにpip.confを設定すると、pipでのインストールの際に「global-optionが指定されているのでバイナリパッケージは使わないよ」というようなメッセージが表示されるようになります。

バイナリパッケージでインストールが当然のWindowsやMac(恐らくIntel上のメジャーなLinuxも)と違い、モジュールのインストールにえらく時間が掛かります。verboseにしない限りはバーが回るくらいですから、根気よく待ちましょう。

global-optionを指定しなかったとしても、FreeBSD9.1用のバイナリパッケージがある可能性はそう高くはないと思いますが。(もしnumpyのバイナリパッケージがあったなら、ビルド済代数演算ライブラリも同梱され、ATLASのインストールなど必要ないことでしょう。Windowsのように。)

そして次章に書きますようにpipでインストールできない場合はsetup.pyでもインストールしますから、distutils.cfgも設定した方が良いのかもしれません。(私はしていません)。

またPythonモジュールのみならず、~/local/lib以下にインストールするライブラリをgccでビルドするときにも「LDFLAGS="-rpath $HOME/local/lib"」を指定したほうが良いのでしょう。(.cshrcに書いておくべきか?そしてこれまでのライブラリは大丈夫なのか?)

Pythonモジュールのインストール

やっとPythonモジュールのインストールの準備が整いました。numpyからインストールします。

numpyのインストール

現時点で最新のnumpy-1.13.3をインストールします。

pipを使いますが、その前におまじないが必要です。

unsetenv SHELL
pip3 install numpy

おまじないの理由は、Github、numpyのissue「Build from sources fails when /bin/tcsh is the default shell #9970」をご参照ください。コンパイルオプションの「-DATLAS_INFO="\"None\""」のダブルクォーテーションがエスケープできずエラーになるようです。

インストールが成功したら確認します。

python3 -c "import numpy;numpy.show_config()"

ここでエラーが起きず、表示された「atlas_3_10_ … _info」「blas_opt_info」「lapack_opt_info」などのカテゴリの「libraries」の項に、「tatlas」があれば成功、ATLASが認識されています。

そしてWebブラウザからtest.cgiにアクセスして、エラーがないことを確認します。(numpy.show_config()はここでも確認できます。)

 

numpyのインストールに、代数演算ライブラリのインストールは必須ではないようです。(但し遅いらしい。)

しかし後にインストールするscipyさんやscikit-learnさんは、代数演算ライブラリがあるかどうかをnumpyさんから聞くようです。ですので一番最初に、ちゃんとATLASなどBLASライブラリを認識したnumpyさんをインストールしたほうがよいかと思います。

そしてscipyさんscikit-learnさんのインストールのときにも、pip3やsetup.pyの前に「unsetenv SHELL」が必要です。以降のインストールを続けて行う場合は良いですが、シェルを開き直した場合はご注意下さい。

scipyのインストール

scipyはpipでインストールしました。バージョンは1.0.0です。

pip3 install scipy

完了までにはかなり時間が掛かります。ご飯を食べに行きましょう。もし会社で5時過ぎでしたら、ディスプレイだけ消して帰りましょう。

成功していたら、numpyと同様に確認します。

python3 -c "import scipy;scipy.show_config()"

エラーが起きず、numpyと同様atlas, blas, lapack関係にtatlasの表示がなされれば成功です。

ブラウザからtest.cgiにアクセスして、エラーがないことも確認します。

scikit-learnのインストール

最初scikit-learnのインストールをpipでしましたら、実行時に「pairwise_fast.soにATL_dasumがないよ」とエラーが出ました。

Github、scikit-learnのissue「pairwise_fast.so is not linked against ATLAS or BLAS #6130」を見ると、lddで見てlibtatlas.soへの参照がないとエラーになるようです。以下のように…

ldd ~/local/lib/python3.6/site-packages/sklearn/metrics/pairwise_fast.so
/home/your-site/local/lib/python3.6/site-packages/sklearn/metrics/pairwise_fast.so:
        libm.so.5 => /lib/libm.so.5 (0x80123d000)
        libthr.so.3 => /lib/libthr.so.3 (0x80145e000)
        libc.so.7 => /lib/libc.so.7 (0x80081a000)

ですので、Githubの0.19.1のタグ(現時点での最新)からリポジトリを引っ張ってインストールします。

wget https://github.com/scikit-learn/scikit-learn/archive/0.19.1.zip -O scikit-learn-0.19.1.zip
unzip scikit-learn-0.19.1.zip
cd scikit-learn-0.19.1
python3 setup.py build_ext --rpath=$HOME/local/lib

ここで一度libtatlas.soが参照されているか確認してみます。

ldd build/lib.freebsd-9.1-RELEASE-p24-amd64-3.6/sklearn/metrics/pairwise_fast.so
build/lib.freebsd-9.1-RELEASE-p24-amd64-3.6/sklearn/metrics/pairwise_fast.so:
        libtatlas.so => /home/your-site/local/lib/libtatlas.so (0x80123d000)
        libm.so.5 => /lib/libm.so.5 (0x8023b1000)
        libthr.so.3 => /lib/libthr.so.3 (0x8025d2000)
        libc.so.7 => /lib/libc.so.7 (0x80081a000)
        libgfortran.so.3 => /home/your-site/local/lib/libgfortran.so.3 (0x8027f4000)
        libquadmath.so.0 => /home/your-site/local/lib/libquadmath.so.0 (0x802b98000)
        libgcc_s.so.1 => /home/your-site/local/lib/libgcc_s.so.1 (0x802dde000)

参照されているようですね。site.cfgで設定はしていなくてもちゃんとnumpyさんから聞くようです。なぜpipからはそうならないのでしょう(謎)。

ともあれインストールを続行。

python3 setup.py install

一応test.cgiで確認していますが、大本のimportだけですので実行時にエラーは出るかもしれません。

gensimのインストール

最後のgensimです。

pip3 install gensim

バージョンは3.2.0でした。

ブラウザのtest.cgiで「Success…」を確認します。

 

以上で目的は達成しました。お疲れ様でした。

(pandas-0.21.1も同様にpipで行けたと思います。)

教訓(Lessons Learned)

以上の作業での、教訓をまとめておきます。

FreeBSDとLINUXの違い

この作業をする前までは、FreeBSDもLinuxもほとんど同じと思っていました。

しかし結構違います。makeとか。それでPortsが存在。

以降は簡単に「ビルドしよう」とは発想しないことにします。

(いや自分でFreeBSDは使わないし、レンタルサーバーでビルドもほぼしませんが。)

探索作業のやめどき

このレポートでは、上流から下流へ書いていますが、実際はまっすぐ海まで下れる流れを下流から少しずつ探していく探索作業でした。

Web検索と試行錯誤の繰り返し。その日ダメでも一晩寝れば突破のアイデアが出てきます。キリがありません。

今回はうまくいきましたが、探索作業のやめどきの決定をどうするか、検討が必要ですね。

Pythonモジュールがインストールできないとき

バージョンを下げてみればインストール出来るかもしれません。

またリポジトリからソースをダウンロードしてsetup.pyの実行でなんとかなるかもしれません。site.cfgの設定やファイルの修正が必要かもしれません。

まとめ

とりあえずscikit-learnとgensimまではインストールできました。しかし正常動作するかはわかりません。

(インストールできたとはいえ、学習やモデルの作成はレンタルサーバーではいたしません。あくまでもCGIでのサービスが目的ですから。)

TensorFlowは無理っす。bazelとかFreeBSDでできる気がしない。

コメントを残す