Bag of ML Words

ML = Machine Learning, Music Love, and Miscellaneous things in daily Livings

小技:linuxでn行おきに何かしたいとき

awk使うマン!

 

# 3行おきに出力

cat file.txt | awk '(NR%3==0){print}'

 

# 10行おきに改行入れる

cat file.txt | awk '(NR%10==0){$0=$0"\n"}{print}'

 

 

qiita.com

読みました:年収は「住むところ」で決まる ─ 雇用とイノベーションの都市経済学

shoeihidoさんの

sla.hatenablog.com

に触発されて、「年収は「住むところ」で決まる-─-雇用とイノベーションの都市経済学」

を買って読んでみました。

結論:かなり面白かったです。読む価値あります。

すらさんありがとう!良い本に出合いました!

 

だいたいまとめると

1) 先進国で低付加価値の製造業が破壊(特に雇用が)されるのはもう避けられない。その代わりに、アイデアや斬新さ、世界を変えるようなイノベーションで駆動する産業が先進国の経済をドライブする。

2) イノベーション駆動の産業は人・組織のつながりでより加速するので、ひとところに企業や優秀な人材があつまる(イノベーションハブ)。集まることでよりハブは強くなるので、その集まった地域だけが急速に地位を向上していくし、イノベーションハブに引き寄せられる優秀企業はそこから抜け出ることがなくなる*1。 人の面でも、イノベーションハブの企業のビジネスは個々人の知的生産性の高さで勝負しているので、優秀な高給取りが集まってくる*2

3)イノベーション産業自体は少数精鋭の高給取りが主役なのでマスを支えることはできないが、イノベーションハブを支える地域経済(スーパーとかレストランとかお医者さんとかクリーニング屋さんとかその他もろもろ)を急速に潤すことができて、かつこの波及効果が製造業よりもずっと大きい。そのため、イノベーションハブでは「すべての知的階級と職層の」給料(と物価)が上昇する。

4) 一方、イノベーション産業から取り残された場所(「ラストベルト」)は相対的に経済的に沈んでいく。このながれをひっくり返すための処方箋はいまだ存在しないし、つまりイノベーションハブを狙って作ることは難しい。

5) 沈みゆく地域から脱出するのは、知的階層の上位に属する人たちがメイン。苦しい目にあう下位の人たちは、情報断絶による機会喪失や、経済的困窮により移住したくてもできないなどの理由でその場所に縛り付けられる。これは比較的引っ越しの多いアメリカでもそうなっている。

 

感想

・一時期、「フラット化する世界」が流行したわけですが、現実には格差は国単位どころか地域・都市単位で発生している状況ですね(東京vs地方)。しかしながら先進国の発展のためには格差を助長するイノベーションハブにますます栄えてもらってもっと税収を上げて国全体に還流させる必要があるという・・・

・アメリカの強さの一つとしてイノベーションハブが多数あること、があるのかなと。日本(東京)、韓国(ソウル)、フランス(パリ)、イギリス(ロンドン)などはハブが一つしかない(あるだけましですが)から、そこに一極集中する。ドイツは伝統的にいろいろ分散しているんですが、その代わりに圧倒的なハブがない。

・日本だと愛知・名古屋圏が「製造業(自動車)のイノベーションハブ」としての機能を維持していると思うのですが、これは何か例外な仕組みが回っているのでしょうか?それともトヨタ系列が痛みにたえているだけ?

・これを見た後に今回のアメリカ大統領選挙、そしてトランプ大統領の「アメリカというかラストベルトへの製造業回帰(と雇用創出)」を切実に必要とする支持層、まだハネムーン期間なのにすでに険悪な対応をとる東西海岸部とそこにベースを置くメディア、なんともなるほど感というか。*3

*1:そこにいないだけで競争が不利になるため。

*2:一方製造業は設備投資・マシンの高性能化で競争力がつくので高価になるのは機械。

*3:製造業回帰で今後永続的に先進国を駆動するのは難しいかもしれませんが、帰ってきてくれた工場が5年だけでも雇用を創出してくれれば次の大統領選挙でも票が集まりそうですね。票取り戦略としては一理ある

Installing CUDA8+CUDNN5.1+Torch on CentOS7 (Japanese/English mixed post)

ほぼ真っ白なCentOSだとあまり情報がないので、自分用のメモもかねて忘れないうちに。

I found there are few posts about CUDA8 + GPU-enabled Torch on 'vanilla' CentOS. Hope this post helps somebody... 

基本ライブラリ群のインストール (Installing very basics)

sudo yum install emacs nano wget git gcc make cmake openssl-devel bzip2-devel readline sqlite-devel hdf5-devel

他にも何かいるかも。

Maybe I forget some libraries...

python

 pipはget-pip.pyを持ってくる

Get PIP by get-pip.py :-)

wget https://bootstrap.pypa.io/get-pip.py

python get-pip.py

pyenvをgit clone

Cloning the pyenv. I do not use virtualenv so far (I do not fully understand the benefit of virtualenv)

git clone https://github.com/yyuu/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile 

 

pythonは今後も考えて3系で進めます。

Use python 3.X based on my personal preference. 

pyenv install 3.5.0

pyenv shell 3.5.0

pip install numpy

pip install scipy

pip install matplotlib

pip install pandas

  

CUDA, CUDNNインストール (Installing CUDA toolkit and CuDNN)

CUDAインストール

事前に、DKMSというライブラリを手動で確保する. Nouveauドライバをblacklistしないといけないかもしれません。ランタイムレベルは変えなくてもいけました。

Install a library called DKMS manually. Maybe you need to disable 'nouveau' drivers by blacklisting. 

wget ftp://rpmfind.net/linux/epel/7/x86_64/d/dkms-2.3-1.20161202gitde1dca9.el7.noarch.rpm

sudo rpm -ivh dkms-2.3-1.20161202gitde1dca9.el7.noarch.rpm

 

NVIDIAからインストールパッケージ(network)をダウンロードします。

Download the CUDA toolkit from the NVIDIA homepage. 

sudo rpm -ivh cuda-repo-rhel7-8.0.44-1.x86_64.rpm

sudo yum clean all

sudo yum install cuda

 

path設定 

Setting the PATHs. 

echo 'export PATH="/usr/local/cuda-8.0/bin:$PATH"' >> ~/.bashrc

echo 'export LD_LIBRARY_PATH="/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATH"' >> ~/.bashrc

source ~/.bashrc 

 

CUDNNインストール

NVIDIAからユーザ登録してCUDNNのパッケージを確保。展開してコピーする。

You first need to register (for free) to utilize CuDNN. After that, get the tgz of the CuDNN. Extract and copy it to CUDA library directory. Easy. 

tar -xvzf cudnn-8.0-linux-x64-v5.1.tgz  

sudo cp -a cuda/lib64/* /usr/local/cuda/lib64/ 

sudo cp -a cuda/include/cudnn.h /usr/local/cuda/include/

 

Torch/Luaのインストール

あえてLUA (not LUAJIT)をインストール。

We install LUA, not LUAJIT. LUAJIT is memory-limited. 

git clone https://github.com/torch/distro.git ~/torch --recursive

cd torch/

bash install-deps   

TORCH_LUA_VERSION=LUA52 ./install.sh   

 

 

必要なモジュール群をインストール. 

Install modules by luarocks. Order matters. 

luarocks install image

luarocks install tds

luarock install cwrap

luarock install torch

luarock install optim

luarocks install nn

luarocks install nngraph

luarocks install cutorch

luarocks install cunn

luarocks install cudnn

luarocks install hdf5

luarocks install luautf8

luarocks install threads

luarocks install penlight

 これでTorchでDeepぶん回せますね!

Now you are ready to rock with Deep NN on Torch!! 

C++学習記(5): boost mpi (+openmpi) on multiple CPUs (machines)

Boost MPIに複数コア分散計算のお仕事は終わったので、いよいよ複数マシンによる盛大な負荷分散をやろうと思う。

 

簡単じゃない?簡単じゃない

 

hostsを指定するファイルを作って

 # nodes_for_MPI.txt

host.1.xx.yyy cpu=4

host.2.xx.yyy cpu=2

 

 mpirun起動時に指定するのみ。簡単じゃない?

mpirun -np 6 --hostfile nodes_for_MPI.txt ./helloBoostMPI

 

ORTE was unable to reliably start one or more daemons.
This usually is caused by:
 

 はい死んだー。

 

sshで直接コマンド渡すとき~

FAQ: Running MPI jobs

のdiagnosisに従うと、まず2番目、ssh経由でコマンド渡すときのpath設定があってなかった。

ということで

ssh-env - ssh実行時に環境変数を設定/変更したい - spikelet days

に従って、/etc/ssh/sshd_configの修正と.ssh/environmentの作成。

pathとかはすべて一つにまとめて直書きする必要があります。

 

sudo service sshd restart

sshdをリスタートして・・。

 

mpirun -np 6 --hostfile nodes_for_MPI.txt ./helloBoostMPI

ORTE was unable to reliably start one or more daemons.
This usually is caused by:
 

まだできない。

 

ファイヤーウォール氏~

--mca plm_base_verbose 10 をオプションとしてつけると、TCP/IPコネクションの問題ぽい。ファイヤーウォールの設定ぽいな・・・。

sudo /etc/init.d/iptable. stop

mpirunをたたく側のマシンのiptableをカット。まあ、社内ファイヤーウォール内だから大丈夫でしょう。。。

 

mpirun --hostfile nodes_for_mpi.txt ./helloBoostMPI
My rank =1 of 6
My rank =4 of 6
My rank =0 of 6
My rank =5 of 6
My rank =2 of 6
My rank =3 of 6

やったねたえちゃん!

C++学習記(4): boost mpi (+openmpi)

ようやく本来の目的であった並列計算に。

最初はOpenMPによるお手軽並列計算を使ってみたのですが、メモリの共有の切り分けがうまくいかず、並列度を上げれば上げるほど遅くなっていく残念な結果に・・・

 

ということで、結局急がば回れ、MPIでちゃんと書くほうが確実。

 

準備

まずはOpneMPIをインストールして、続いてMPIを使いやすくしたboost mpiを利用するためにboostを(再)インストール。

 

情報源としては↓がいい感じです。

kawa0810.hateblo.jp

 

ただ、boost 1.61だとusing mpi ;がうごかないことが何度もあったので注意。こういう時は本家(Getting started - 1.61.0 )を見に行って、それに従うのが吉。

結局、.user-config.jamとproject-config.jamの両方

using mpi : your/own/path/to/opnempi/bainaries ;

の形式の1文を追加して突破しました。

 

CMake

CMakeLists.txtは以下のような感じになりました。ただ、環境によって動かなかったりするのも経験したので、これを下敷きにしていろいろ試行錯誤するしかないみたいです。もっとスマートな書き方とかがあったら教えてください。

cmake_minimum_required(VERSION 2.8)
project(boostmpi_test)

add_definitions("-Wall -std=c++11")
add_definitions("-O3")

set( BOOST_ROOT "/usr/local/boost-1.61.0_gcc-4.9.2_mpi")
FIND_PACKAGE(Boost 1.6 COMPONENTS mpi serialization REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
set( CMAKE_C_COMPILER mpicc )
set( CMAKE_CXX_COMPILER mpicxx )

add_executable(helloBoostMPI helloBoostMPI.cpp)
add_executable(testScatter testScatter.cpp)
add_executable(testBroadcast testBroadcast.cpp)
add_executable(testGather testGather.cpp)

TARGET_LINK_LIBRARIES(helloBoostMPI ${Boost_LIBRARIES} -lboost_mpi -lboost_serialization)
TARGET_LINK_LIBRARIES(testScatter ${Boost_LIBRARIES} -lboost_mpi -lboost_serialization)
TARGET_LINK_LIBRARIES(testBroadcast ${Boost_LIBRARIES} -lboost_mpi -lboost_serialization)
TARGET_LINK_LIBRARIES(testGather ${Boost_LIBRARIES} -lboost_mpi -lboost_serialization) 

 

サンプル

せっかくなので、動作と使い方確認用に作成したソースを公開しておきます。

github.com

 

基本的に

boostjp.github.io

を焼き直しただけなんですが・・・

C++ 学習記(3): vector

C++といえばvectorというくらい、配列は全部vectorにするのがいいっぽい。

 

どこで見たのか覚えていないのですが、webで見つけた資料を基に

vectorの挙動を調べるためのコードを書きました。ふーんって感じ。

*1

 

#include <iostream>
#include <vector>
#include <string>
using namespace std;

typedef vector<float> fvec;

void print(const char* str, vector<int> &v){
if(v.empty()){
cout << "コンテナ" << str << "は空です。" << endl;
cout << str << "の要素数 is " << v.size() << endl;
} else {
vector<int>::iterator it;
cout << str << "の要素数 is " << v.size() << endl;
for (it = v.begin(); it != v.end(); it++){
cout << " " << *it;
}
cout << endl;
}

}

void print(const char* str, fvec &v){
if(v.empty()){
cout << "コンテナ" << str << "は空です。" << endl;
cout << str << "の要素数 is " << v.size() << endl;
} else {
fvec::iterator it;
cout << str << "の要素数 is " << v.size() << endl;
for (it = v.begin(); it != v.end(); it++){
cout << " " << *it;
}
cout << endl;
}

}

int main(){
int i1;
vector<int> v1;
vector<int> v2(10, 3);
fvec fv1;
fvec fv2(5, 3.5);

/* initalize */
cout << "*** initialize a vector ***" << endl;
print("v1", v1); // should be empty
print("fv2", fv2);

for(i1 = 0; i1 < 10; ++i1){
v1.push_back(i1);
fv1.push_back( (float)i1 * 1.1 );
}
cout << "# v1.push_back(i1);" << endl;
print("v1", v1);

cout << "# fv1.push_back( (float)i1 * 1.1 );" << endl;
print("fv1", fv1);

cout << endl;
cout << "*** clear a vector ***" << endl;
fv1.clear();
cout << "# fv1.clear()" << endl;
print("fv1", fv1);


/* vector of vectors */
cout << endl;
cout << "*** initialize a vector of vectors ***" << endl;
vector<fvec> vector_of_fv;
for(i1 = 0;i1 < 3; ++i1){
fvec new_fv(fv2);
vector_of_fv.push_back(new_fv);
}
// check if the above push_back is reference or deep copy
fv2[0] = -1.9;

cout << "# fvec new_fv(fv2);" << endl;
cout << "# vector_of_fv.push_back(new_fv);" << endl;
print("fv2", fv2);
for(i1 = 0;i1 < 3; ++i1){
string str = "vector_of_fv[" + to_string(i1) + "]";
print(str.c_str(), vector_of_fv[i1]);
}

for(i1 = 0;i1 < 3; ++i1){
vector_of_fv[i1][i1] = -1.2 * i1;
}
cout << "# vector_of_fv[i1][i1] = -1.2 * i1;" << endl;

for(i1 = 0;i1 < 3; ++i1){
string str = "vector_of_fv[" + to_string(i1) + "](modified)";
print(str.c_str(), vector_of_fv[i1]);
}


}

出力結果

$ ./a.out [~/projects/CPP]
*** initialize a vector ***
コンテナv1は空です。
v1の要素数 is 0
fv2の要素数 is 5
3.5 3.5 3.5 3.5 3.5
# v1.push_back(i1);
v1の要素数 is 10
0 1 2 3 4 5 6 7 8 9
# fv1.push_back( (float)i1 * 1.1 );
fv1の要素数 is 10
0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9

*** clear a vector ***
# fv1.clear()
コンテナfv1は空です。
fv1の要素数 is 0

*** initialize a vector of vectors ***
# fvec new_fv(fv2);
# vector_of_fv.push_back(new_fv);
fv2の要素数 is 5
-1.9 3.5 3.5 3.5 3.5
vector_of_fv[0]の要素数 is 5
3.5 3.5 3.5 3.5 3.5
vector_of_fv[1]の要素数 is 5
3.5 3.5 3.5 3.5 3.5
vector_of_fv[2]の要素数 is 5
3.5 3.5 3.5 3.5 3.5
# vector_of_fv[i1][i1] = -1.2 * i1;
vector_of_fv[0](modified)の要素数 is 5
-0 3.5 3.5 3.5 3.5
vector_of_fv[1](modified)の要素数 is 5
3.5 -1.2 3.5 3.5 3.5
vector_of_fv[2](modified)の要素数 is 5
3.5 3.5 -2.4 3.5 3.5

 

参考文献

完全にC++は未知だけどもJavaなら結構経験積んでいたので、私の知り合いの中で最もプログラミングに長けた大先輩におすすめしていただいた

を買いました。とりあえず、わからないことがあったらこれにあたってみると、1つくらいは例が載っているのでだいたい乗り切れています。*2

*1:でも、まだ各要素にアクセスするときはfor(int i)にしちゃう(イテレータに慣れてない)

*2:const参照とか&, *の使い方とか私にとっては完全に悪夢なので、毎回見ています

C++ 学習記(2): cmake

IDEが使えない可能性を考慮して、C++はlibtool chainかcmakeで何とかしようと思っていた。

で、とりあえずcmakeが簡単そうだったのでやってみる。

 

情報源は

ごく簡単なcmakeの使い方 - Qiita

Learning CMake <-- これ素晴らしい!

 

いま、cmake_testというディレクトリ内に

HelloCPPWorld.cppというC++ファイルだけが存在している。

 

このとき、最低限として以下の内容をCMakeLists.txtというファイルに書く。

 

HelloCPPWorld.cppを作っておく。

Add_definitions("-Wall -std=c++11")

Add_executable(Main HelloCPPWorld.cpp)

 

// HelloCPPWorld.cpp
#include <iostream>

int main(){
std::cout << "Hello CodeLite World";
return 0;

}

 

この状況で、

cmake .  <-- makefileを生成

make

とするとMainという実行ファイルができる。

 

cmakeはヘッダファイル(hpp)の必要なものを指定したパスから買って見つけてくれるので、MakeFileより書くのが楽。