Bag of ML Words

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

C++ 学習記(1): まずは環境確認整備

業務の都合でいままで書いたことのないC++を使わざるを得なくなった。

業務のほうは既存のC++コードを書き換える方向なので、まあなんとかなるだろうと思っているんだけど、スクラッチから起こすことができないので

makeの書き方も-Iや-Lオプションの意味もautomakeも何もわかっていない。

 

ということでやばいだろうということでよちよち勉強していくことにする。

 

やらないといけないであろうこと

MakeFileの読み方書き方、automake, cmake

コンパイルオプション

ldconfig, LD_LIBRARY_PATHの意味と設定方法を理解する

OpenMP / MPIによる並列化

 

参考文献

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

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

 

設定

プログラム経験: Java(メイン、10年以上), Python(ここ2年ほどメインで使ってる)

OS: ubuntu14.04 on VMware

エディタ: emacs

IDE: JetBrains IntteliJ IDEAとPycharmがないとJavaPythonもかけない

IDE絶対ほしいけど、JetBrainsのC++って有償なんだよね、確か・・・

現在の状況

何が入っているか確認するのもあってapt-get installでそれっぽいライブラリを指定してみる。

 

f:id:Dr_KayAi:20160811231224p:plain

ちょっと探すと

bokko.hatenablog.com

 

という記事が見つかったので、載っているやつはインストールしておく。

 

Hello, world

まずはhello world

(hello.cpp.cpp)

#include <iostream>
#include <cstdlib>

int main(){
std::cout << "hello world" << std::endl;
return 0;
}

 

コンパイルして実行。

% g++ hello_cpp.cpp

% ./a.out

Hello world.  

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

Linux便利コマンドの覚書

コマンドラインでいろいろ文字列処理できるよっていうね。

常にpythonperlさん使うより、覚えていたらずっと早かったりする。

そこで、便利だったコマンドを、実際の自分のusageに即してメモする。

というか100本ノックの第二章やってるだけです

 

www.cl.ecei.tohoku.ac.jp

 

cut

デフォルトでは、タブ区切りファイルからコラムを切り出せる。

tsvファイルがあったときに、その第1, 3コラムだけを抽出するには

cat hoge.tsv -f1,3 

結果がほしいときは

cat hoge.tsv -f 1, 3 > output.tsv

とする。

 

区切り文字を変える時には-dをつける

cat hoge.csv -d',' -f2

など

 

sed

文字列変換。

sed -e 's/ABC/DEF/g' hoge.txt > replaced.txt

で、hoge.txt内の"ABC"がすべて"DEF"に置換されてreplaced.txtに出てくる

 

paste

二つのファイルを、同じファイル行数ごとに連結する。

これ、実はすごく強力ではないか?入力ストリームを2つ同時に進めるってのは普通のプログラムだと難しいような気が(少なくとも perlの <>だけではできない?)

paste file1.txt file2.txt > file12.txt #concat with tab (default)

paste -d":" file1.txt fil2.txt > file12-colon.txt # concat with colon. -d to specify the connecting character

paste -d"ABC" fileq.txt file2.txt > file12-A,txt # どうも文字列の最初の1文字しか使わないようだ。この場合は"A"で連結される

 

 sort

入力されたファイルを、ソートして並べ替える。

これまた神コマンドかもしれない。

例えば

高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10

みたいな(タブ区切り)データがあったとき

sort -n -k3 data.txt # 第3列 (-k3)を、数値として(-n)、昇順にソート

大阪府 豊中 39.9 1994-08-08
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
山形県 酒田 40.1 1978-08-03

sort -n -k3 -r data.txt # -rで降順になる

山形県 酒田 40.1 1978-08-03
群馬県 前橋 40 2001-07-24
岐阜県 美濃 40 2007-08-16
大阪府 豊中 39.9 1994-08-08

 これは圧倒的便利

 

cat

cat自体はまあ普通だけど、頭のよい使い方を

cat コマンド | コマンドの使い方(Linux) | hydroculのメモ

で見かけたので下記に引用する。

 

行数が膨大なテキストファイルに対してなにかの処理をしたい。

処理に時間がかかってしまうが、その “なにか” を処理させるワンライナーが正しいかどうか不安で何度か試行錯誤する必要がある場合に、試行錯誤中は、テキストファイル全体を処理するのではなく、headでファイルの一部だけを処理してみる。

ワンライナーが完成したときに、コマンド履歴の headcat に書き換えるだけで処理を完成させることができる。

“なにか” が仮に文字コード変換だとすると、こんな感じ。

## テキストファイルの文字コードがわからないが、とにかくUTF-8にしたい
$ head huge.txt | nkf --guess
CP932 (CRLF)

## CP932 というのをUTF-8にするにはどうしたらいいんだっけ?
$ head huge.txt | nkf -sW
...

## 違った、文字化けしちまった、こっちかな?
$ head huge.txt | nkf -Sw
...

## 合ってた。さて、改行コードはどうなってる?
$ head huge.txt | nkf -Sw | nkf --guess
UTF-8 (CRLF)

## 改行コードも直したい
$ head huge.txt | nkf -Sw -Lu | nkf --guess
UTF-8 (LF)

## OK。じゃあ、本番
$ cat huge.txt | nkf -Sw -Lu > result.txt

最後の本番のコマンドは nkf -Sw -Lu huge.txt > result.txt でもよいのだが、直前のコマンド履歴のheadcat に書き換えるだけのほうが、タイピングが楽で間違えないのである。このとき cat はほとんど意味のある仕事をしないが、タイピングを楽にすることに意味がある。

 

 

screenの使い方!

実に10年ぶりくらいぶりにマシンをつけっぱなしにできない状況になったので、改めてscreenを再勉強。

 

screenの特徴は、一つのターミナル画面上で番号の切り替えで多数のセッションを作ることだけど、もう一つの特徴として「セッションはバックグラウンドで走っているのでそのターミナルを殺しても生き残る」というのがある。

 

ので、手元のマシンからsshで計算サーバにログイン、計算を回すという状態のときに

i) 計算サーバでscreenして新しい仮想ターミナルを作成、ログイン

ii ) 計算ジョブを投げる

iii) screenしたターミナルから抜ける

と、あとはsshが切れても計算サーバ上では ii) のジョブが生き残ってくれる。

で、後日改めて計算サーバ上でscreenしていたターミナルにログインすれば計算結果が回収できるというわけ。

 

portforwarding + autossh + sshfsと合わせて利用するので、ここで必要なコマンドを備忘録的にメモ。

 

新しいスクリーンを始める: 

screen

スクリーンから離れる: detach from screen(殺さないで親ターミナルにもどる)

Ctrl-a d

入れ子でスクリーンするとわかりにくいので、新しくスクリーン作るときはいちいちスクリーンから離れて、親ターミナルに戻ったほうが良さげ。

 

今あるスクリーンを調べる: list screens

screen -ls

スクリーンのIDが並びます

 

指定のスクリーンに戻る: resume screen 

screen -r ID

 

スクリーンを殺す

exit

ただのターミナルなのでね

ansible導入テスト(Docker, Jenkinsへの道 on Windows(3))

続いて、構成管理ツール(?)であるansibleを試す。

 

ansibleのほうがchefよりも後発でネガをつぶしているのと簡単構成向きらしい。

 

 

試す

qiita.com

これにならって、サーバ二つ構成の最小セットアップをvagrant + virtual box上に構成、そこで片方のサーバでもう片方をansibleで管理するテストを行う。

 

作った環境ではcentos6.5なので、Vagrantfileはちょっとだけ変わる。

Vagrant.configure(2) do |config|
  config.vm.define "controller" do |node|
    config.vm.box = "centos65"
    config.vm.hostname = "controller"
    config.vm.network "forwarded_port", id: "ssh", guest: 22, host: 2210
    config.vm.network "private_network", ip: "192.168.100.10"
  end
  config.vm.define "target" do |node|
    config.vm.box = "centos65"
    config.vm.hostname = "target"
    config.vm.network "forwarded_port", id: "ssh", guest: 22, host: 2220
    config.vm.network "private_network", ip: "192.168.100.20"
  end
end
 

 vagrant upで長らく待つとちゃんとcontrollerもtargetも起動する。

 

こけた

ちょっと何かupdateしてしまったら、ビルドが壊れた・・・

kernel-develのversion有ってないよってなる。

そのときは

qiita.com

を参照して下さい。

 

無事起動したらansibleインストール

f:id:Dr_KayAi:20160527235022p:plain

よしよし。ということでcontrollerサーバにsshして、ansibleをyum installする。

f:id:Dr_KayAi:20160527235327p:plain

あれ、なんかtargetになってるが、まあいいや。

targetからcontrollerを支配しよう・・・・

f:id:Dr_KayAi:20160528001050p:plain

つながったポイ??

 

 

「オブジェクト指向と10年戦ってわかったこと」が素晴らしかった

qiita.com

これです。

 

自分はJava使い*1なのですが、オブジェクト指向の価値を全然活かせていないなぁと常々思っていました。

色々原因がありそうですが、この記事にあるようにしっかり考えてないからだ、ということがわかりました。

 

幾つか、自分に刺さったところを自分のために引用しておきます。

気になった人はリンク先の本文をぜひ読んでください。

 

クラスはとっかえひっかえするものをクラスにする

オブジェクト指向で書く理由、それは変更に対して柔軟に対応するためです。

(省略)

オブジェクト指向によるアプリケーション開発は、変更されない箇所を軸に、頻繁に変更される箇所をクラスに抽出するプログラミングスタイルです。

 

 

継承は様々な具体的なクラスを抽象化するためのボトムアッププロセスで、トップダウンにすべきではない

継承は機能を受け継ぐためのものではありません。継承の本質は、犬や猫を「動物」という抽象概念としてまとめ上げられるインターフェイスなのです。 

 

その証拠として、別のクラスの機能を利用する方法にコンポジションがあります。コンポジションを使えば人間がパーツを組み合わせて「車」を作るような自然なオブジェクトの作り方ができるし、実は継承よりコンポジションの方がよく使います。

 

ポリモーフィズムは抽象のスーパークラスを扱う(ことによって見通しを良くする)

継承の本質はインターフェイスであると説明しましたが、ポリモーフィズムはそのインターフェイス(抽象)に対してプログラムするということです。 

 

インスタンスをnewするのはメインクラス。メインクラスは素材を出して処理する調理場。

そのため、ファクトリを作るまでもないインスタンス生成はメインクラスで行うようにしましょう。メインクラスでnewしたインスタンスを他のクラスに渡すのです!

(省略)

メインクラスは調理場のような存在であり、メインクラスに疎結合性やモジュール性は必要ありません。そのため、メインクラスがnewの接着剤でベトベトに汚れてしまっても何も困ることはないのです。

 

カプセル化は難しい

しかし、小刻みにブレーキを踏まなければスリップし、小まめにギアチェンジする必要があり、カーブするときは倒れないように体重移動をしなければ倒れてしまう自動車があったら、僕はそれを運転できません。複雑だからです。だけど、ブレーキにはABSを搭載し、ギアはオートマチックで、カーブするときは倒れないよう重心が設計されていれば、あれこれ考えず運転できます。

つまりカプセル化とは複雑な部分を隠し、無駄な操作をしなくても良い状態にそのものを洗練させ、分かりやすい状態にするということです。

(省略)

実はこの「無駄を省き洗練させてわかりやすくする」というのはオブジェクト指向の原則というより、より抽象度の高い「デザイン」の原則なのです。

オブジェクト指向に不可欠なのはカプセル化ですから、つまり、オブジェクト指向でプログラミングする人にはデザインのセンスが必要になるということになります。

そんなもの、難しくて当然です!

 

 カプセルにはただしい名前が必要

自動車には「自動車」という名前が、エレベーターには「エレベーター」という名前が付けられています。もしあなたが何かをカプセル化した場合、そのものにまだ名前が付いていない時は、それに正しい名前をつけるということが、カプセル化の最後の仕上げになります 

 

*1:そしてC++使いになりたいわなびー

Ubuntu-based Docker imageでDocker初体験(Docker, Jenkinsへの道 on Windows(2))

最初はvagarnt上のcentosで改めてvirtual box, vagrant, そしてdockerと思っていたのですが・・・

 

こけたので、バイパスルート。

とりあえずvirtual vox + vagrantができたのでcoreosを落としてきます。

それには初めからdockerあるらしいので!(あるだけだと思うけど)

 

qiita.com

 

これに完全にならうだけ(何の工夫もしない)・・・できた。DockerでUbuntuhello worldってechoした!

(本当にそれだけ。使い方もわかってない)