2016年11月6日日曜日

Doxygenを使ってみる

仕事で長年維持してきたプログラム(C++です)を久しぶりに大改造する機会ができそうなので、ちょっとリバースしたくなりました。(昔つくったもので、ドキュメントがほとんどない!しかも、その時々で人が変わって手をいれてきたので、かなり怪しい構造になってきている可能性があり、維持性に問題がでてきています。

真っ先に確認したいのが、誰からもCallされなくなった関数のチェックです。こういうのが残っていると、後から維持に携わる人も、うっかり触れなくなってしまい余分な手間が増えるだけです。
まあ、この手の機能は静的解析ツールなら大抵は持っていますが、Doxygenでやってみることにしました。(個人的に使ったことはなかったんですよね)

windowsのバイナリをDLするのが簡単そうなんですが、とりあえず慣れているLinuxでやってみます。(調べたら、macでもbrewコマンドでできそうです)

Ubuntuなら、apt-getで簡単にインストールできます。

$ sudo apt-get install doxygen doxygen-gui graphviz

doxygenが本体のパッケージ、doxygen-guiはGUIのユーザーインターフェース、graphvizはコーリングリストのツリーを図で生成するのに必要なパッケージになります。

インストールが終わったら、以下のコマンドで起動。


$ doxywizard


Step1の動作領域がよくわかりませんが、何らかの作業用ファイルを作るエリアなんでしょう。(注:これは設定ファイル:Doxyfileをここに置きます)Project nameとかは適当に入力して、解析したいプログラムのフォルダと、生成したドキュメントを格納するフォルダだけはきちんと入力します。


ここの設定で、コーリングリストを生成してくれます。(これが今回の目的)デフォルトはオフなので注意。
あとは、その他のオプションを設定して、runするだけです。

大層なGUIがついていますが、やってることはDoxyfileの設定をしているだけなので、必要な設定だけテキストエディタで手動でできるなら、そちらのほうが早いかも。以下に、設定ファイルで設定したほうがいい主な項目を挙げておきます。


option
default
description
PROJECT_NAME
"My Project"
クラス図を作成したいプロジェクトの名前
EXTRACT_PRIVATE
NO
privateなメンバ変数・メンバ関数も出力する
EXTRACT_STATIC
NO
staticなメンバ変数・メンバ関数も出力する
EXTRACT_ANON_NSPACES
NO
匿名の名前空間についても出力する
RECURSIVE
NO
ソースコードを再帰的に検索する
HAVE_DOT
NO
YESに設定するとgraphvizなどの描画ツールを使用してクラス図を出力する
DOT_NUM_THREAD
0
スレッド数
CALL_GRAPH
NO
関数やメソッドを呼び出す側の依存関係を描画する
CALLER_GRAPH
NO
関数やメソッドを呼び出される側の依存関係を描画する

面倒くさい人は、解析したプログラムのソースコードのルートに設定ファイルを以下のコマンドで作り、

$ doxygen -g

できたDoxyfileの上記項目を好みで設定して、

$ doxygen

と実行してやれば、解析結果が出力されます。


2016年10月12日水曜日

macにゲストアカウントが表示された!?

macosxが新しく、macos Sierraになり少し様子を見て問題がなさそうなので、自宅のMacBookProを更新しました。更新は特に問題なく進み、インストールしてある既存のアプリにも特に問題がないようです。(実は、更新直前に気づいたのがいつのまにかBlenderが起動しなくなっていました。2年ほど更新サボってたからな〜 Sierraにしてから最新のBlenderにしたら問題なく動きました。)

ところで困ったのが、PowerOn時の画面にゲストアカウントが表示されるようになってしまったことです。これまでそんな表示なかったのにと思い、調べて見たら結構以前のOS更新の時からそういうトラブル(更新したらゲストアカウントが表示されるようになってしまった)があったようです。設定の「ユーザとグループ」でロックを解除して、ゲストログインが許可になっているのを不許可にするだけです。
だけどこれって、いつからか知りませんがゲストアカウントが子供用のペアレンタルコントロールにも使われる様になったようです。

しかし、OSの更新で勝手にゲストをONにしないで欲しいな〜(Appleは何を考えているんだ?)

2016年8月16日火曜日

windows10 アニバーサリーUpdateでbashを試してみる

ちょいと勇気がいりましたが、windows10でanniversary updateを行い(通知が来ないので手動でやりました)、bash on windowsを試してみました。

やり方は各種サイトにありますので割愛しますが、とにかく再起動が多い!なんか懐かしい風景です。(昔はシステム更新なんかだと、こんなんばっかだった)さて肝心の"bash on windows"ですが、なんというかvirtual boxでubuntuが動いているような感じです。それとも、今はやりのコンテナに仕立ててきたのか?そんなに重くはないんですが、問題は文字コードが…
何書いてあるのかわかりません。対策をあちこち知らべましたが、どうも決め手がないようです。まだマシンによって差がでてしまうようです。

ただそれ以外は普通にubuntuが動いています!いや、これは素晴らしい。これができると、これまでプログラム作るとき、macに逃げていたのが、windowsでもやってみるか、という気になります。(それが狙いだという話もありますし)

しかし、GUIはどうするんだろう?APIが全く違うし、windowsのGUI関係のAPIの一部でもこのシステムに取り込むのは大騒ぎになるだろうし。web系のサーバに使ってくれないかな、というM$の考えなんだろうけど、まだTCP/IPのAPIが完全には機能していないらしいし、今後どうなるのかな。(個人的にはCygwinが嫌いなんで、ある程度残って欲しいんですが、かなり今の状況では怪しいです。何か使い道を考えてあげないと)
ただ無理にGUIのAPIを移植しなくてもいいと思います。今、時代はwebですべてすますのが本流なんで、GUIはブラウザにまかせてしまえばいいですから。難しいのは不安定なwindows OSの上で如何に安定して動く環境にできるかですが、こればっかりはかなり難しいかな。

PS
どうもanniversary updateにしたのは早まったようです。ファイルの移動とかでおかしな挙動が見られます。
あと肝心のbashですがどうにも日本語が表示できないので、以下の設定で動かしています。

$ LANG=en_US.UTF-8

要は英語表記でアラートとか出してね、ですね。あと、一体どういう環境になっているのかわからないのですが、コンテナでもないようで、ping、ifconfig等のネットワーク系のコマンドが実行できません。ベータ版とは聞いていますが、どんな実装になってるんだ???

2016年8月12日金曜日

SQLite3のプログラムの勉強

ちょっとSQLite3を使ったプログラムをWindowsで作るとどうなるのか調べてみたくなりました。ただ私は普段LinuxかMacでプログラムを作ることが圧倒的に多いので、まずは慣れたMac、Xcodeで作ってみます。

1. sqlite3のインストール
brewを使ってインストールしています。コマンドラインでも使えますし、ヘッダ、ライブラリも一緒にインストールしてくれます。

2. プログラムの作成
とりあえず、以下の様なプログラムを作ってみました。
//
// main.cpp
// SQLiteTest
//
// Created by hiro on 2016/08/11.
// Copyright © 2016年 hiro.maeda. All rights reserved.
//
#include <stdlib.h>
#include <iostream>
#include <sqlite3.h>
int main(int argc, const char * argv[]) {
// dbファイルを指定した場所に作るための確認用コード
std::string home = getenv("HOME");
std::cout << "$HOME = " << home << std::endl;
home += "/ProgWork/SQLite";
std::cout << "$HOME = " << home << std::endl;
// ここから本体
std::string dbfile = home + "/test.db"; // DBファイル
sqlite3* db = NULL;
// dbのオープン
int err = sqlite3_open(dbfile.c_str(), &db);
if (err != SQLITE_OK)
{
// dbファイルオープン失敗
std::cout << "OPEN ERROR " << err << std::endl;
exit(-1);
}
std::cout << "OPEN SUCCESS!" << std::endl;
// SQLの実行(insert)
char* errCode = NULL;
err = sqlite3_exec(db, "insert into tbl_test(id, name) values('123', 'hoge');", NULL, NULL, &errCode);
if (err != SQLITE_OK)
{
// SQL実行失敗
std::cout << "INSERT ERROR " << err << ":" << errCode << std::endl;
err = sqlite3_close(db);
exit(-1);
}
// SQLの実行(select)
sqlite3_stmt* pStmt = NULL;
// データの抽出、ステートメントの用意
err = sqlite3_prepare_v2(db, "select * FROM tbl_test where id=123", 64, &pStmt, NULL);
if (err != SQLITE_OK)
{
// SQL実行失敗
std::cout << "SELECT ERROR " << err << std::endl;
err = sqlite3_close(db);
exit(-1);
}
else
{
// データの抽出
while (SQLITE_ROW == (err = sqlite3_step(pStmt)))
{
int id = sqlite3_column_int(pStmt, 0);
const unsigned char* name = sqlite3_column_text(pStmt, 1);
std::cout << "id: " << id << ", name: " << name << std::endl;
}
if (err != SQLITE_DONE)
{
std::cout << "SELECT DONE ERR" << std::endl;
err = sqlite3_close(db);
exit(-1);
}
}
// ステートメントの解放
sqlite3_finalize(pStmt);
// dbのクローズ
err = sqlite3_close(db);
if (err != SQLITE_OK)
{
// dbファイルクローズ失敗
std::cout << "CLOSE ERROR " << err << std::endl;
exit(-1);
}
std::cout << "CLOSE SUCCESS!" << std::endl;
return 0;
}

とてもシンプルです。実行結果は以下の様になります。

$HOME = /Users/hogehoge
$HOME = /Users/hogehoge/ProgWork/SQLite
OPEN SUCCESS!
id: 123, name: hoge
CLOSE SUCCESS!

createがありませんが、そこはマニュアルで作っています。(プログラムに書いてもいいんですが、毎回実行するためにいちいちdbファイルを削除するのも面倒なので。)

> create table tbl_test(id integer primary key, name text);

最終的にはinsertのところをupdateに変えて、プロセス間の通信代わりに使おうと目論んでいます。

3. 注意点

  • Xcodeの設定でライブラリの追加オプション"-lsqlite"を忘れない様に。
  • 単純にやろうと思うなら、sqlite_open(), sqlite_close(), sqlite_exec()だけで済ますこともできます。ただselect文をsqlite_exec()でやろうとすると、どうしても出力をcallbackで受けないといけなくなります。callback関数を書くのが面倒だったので、非同期クエリで実装しています。(こちらも面倒だがやむを得ません)
  • sqliteはsql文の実行ではデフォルトでオートトランザクションになっています。将来的にプロセス間の通信に使うつもりなら本当は、"bgein","commit"と明確にトランザクションの指定をしてやるべきです。ただそんな複雑な通信は当面する気がなく、一方向だけ(片方がwriteして、他方はreadするだけ)のつもりなので、当面はこれでも問題はありません。
さて、これをwindowsのVisualStudioのc++で実装です。2015ではUWPアプリ(Universal Windows Platform)として、SDKにsqlite3が標準で入っているらしいです。実装もこのままでコンパイルが通りましたが、リンクでどうしてもsqlite関係の関数が「未解決の外部シンボル」と言われてしまいます。(ちゃんとwinsqlite3.libを追加のライブラリに指定しているんですが・・・)ちょいとこの問題の解決には時間がかかっています。


2016年6月18日土曜日

ofstreamのバッファサイズ

以前から思っていたんですが、c++のプログラムで1つのファイルの中のデータを複数のデータに分類して出力するプログラムが、どうにも時間がかかると。

まあ、100MB以上のファイルを数百のデータに分類する場合などかなり処理が重いとはわかっているんですが、にしても耐え難くなってきました。色々、ぐぐってみるとやはりofstreamは昔のcのfwrite()に比べるとかなり遅いようです。(持っている機能が段違いなので、プログラム作成の手間を考えると今更ofstreamをfwrite()に戻す気にはなりませんが)

そんななか、ofstreamのバッファを大きくすると速くなるとの話を見つけました。ちょっと試してみます。(10MBのテキストファイルを作成するだけです)

#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
const int bufsize=100000;
char buf[bufsize];
ofstream os;
os.rdbuf()->pubsetbuf(buf,bufsize);
os.open("test.txt", ios::out);
for (int i=0; i<10000000; i++)
{
os << "a";
}
os.close();
return 0;
}
view raw test1.cpp hosted with ❤ by GitHub
実行してみると、一瞬で終わります。そこで、わざとバッファサイズを小さくしてみます。

include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
const int bufsize=2;
char buf[bufsize];
ofstream os;
os.rdbuf()->pubsetbuf(buf,bufsize);
os.open("test.txt", ios::out);
for (int i=0; i<10000000; i++)
{
os << "a";
}
os.close();
return 0;
}
view raw test2.cpp hosted with ❤ by GitHub
極端ですが、いきなり10秒以上処理に時間がかかるようになりました。

ところでデフォルトのバッファサイズはどれくらいになっているんでしょう?あとどのくらい大きくしても大丈夫なんだろ?(実は大きいほどいいかと最初は思い、bufsizeを100MBなんてやったら、プログラムが動かなくなりました。それもファイル出力をしているサブルーチンに入ったところで異常終了!全然理由がわかりませんが、どうもサブルーチンのローカル変数としてバッファを定義したので、スタックエリアに問題が出たんでしょう。)このあたりは、プログラムやそれを動かすシステムの性能にもよるでしょうから、一口には中々言えないところでしょう。

2016年4月10日日曜日

Jetson TK1に外部SDをmount

さて、一通り設定が終わり、chainerもかなり苦労しましたが無事インストールできました。(Jetson TK1にはcuDNNが入っていると聞いていたんですが、chainerインストール時に、なぜかcコンパイラが動き出し(CUDAを使えるとインストーラが自動的に認識し、再ビルドしだしたのか?)、"cudnn.hがない”と散々怒られました。ただ、このインストーラが素晴らしく、それでも何とかpyCudaは使えるようにしてくれたようです。
後で調べたら、TK1だとcuda-6.5くらいまでが無難にインストールできて(自分もそうしましたが)、cudnnはcuda-7.0からだそうです。(最新は7.5ですが、それがインストールできたら、一度chainerを pip uninstall chainer して再度入れ直さないとダメだそうです。

1. cudaの威力を確認する
何か時間のかかるもので、威力を確認したくなります。調べていたら、chainer-goghというのが面白そうです。詳細は省きますが、元イメージ + スタイルイメージ = 合成イメージ を作ってくれます。何でこれがDeepLearningなのかよくわかりませんが、caffeの出来合いのモデルを使うそうです。
まず、MacBookProで試してみると、2時間ちょっとかかりました。(下手な古いPC使うと、1日くらいかかるらしいです)
さて、Jeton TK1ですが30分で処理が終わりました。(他のブログにも記事があり、そちらでも30分くらいなので、設定はうまくいっているのでしょう)
速いといえば、速いのですが意外にMacBookProが早くてびっくりです。(こいつのビデオチップはintel内蔵を使っていますので、OpenCVはできてもCUDAは動きません)

2. 外部SDを使えるようにする
Jetson TK1の内蔵SDは16GBしかなく、しかもubuntuのOSやらcudaの設定で5GB以上使ってしまいます。このままchainerを試すそうとしても、すぐにSDが一杯になるのは目に見えてます。
そこで外部SDをつけて、ファイルシステムとして使えるようにしました。

(1)ext4でフォーマットする
基本、SDカードの初期状態はwindowsで使うことを考えてvfatです。しかしそれでは都合が悪いので、ext4でフォーマットします。

$ sudo cfdisk (デバイス名)  # これでまずvfatのパーティションを削除します

デバイズ名は自分の場合は、/dev/mmcblk1でした。(内蔵SDが/dev/mmcblk0でした)調べる一番簡単な方法は、Jetsonを起動しておいて、SDをさすと自動的にマウントされます。そこで、df -h してみるなり、dmesg | tail なりすればわかります。
次にフォーマットです。

$ sudo mkfs.ext4 (デバイス名)-L (ラベル名)

最後の「ラベル名」は必須ではありませんが、つけておくとfstabを書くのが楽になります。

(2)SDカードをマウントする
さてここで/etc/fstab の設定になるのですが、なぜか自分のJetsonでは中身が空っぽです。これどうやって、内蔵SDのマウントしてるんだ?しかもコメントとして、"UNCONFIGURED FSTAB FOT BASE SYSTEM"と書いてあるし不安になってきました。とりあえず調べた通り以下の設定を追加しました。

LABEL=(ラベル名) (マウントポイント) ext4 defaults 2 0

ためしに、sudo mount -a で問題なくマウントできることを確認します。

(3)Jetsonを再起動して自動的にマウントされるかを確認する
自分の場合、ここまでくるのに随分失敗しました。試行錯誤して、これまでのコマンドを何度もやり直しましたし、(2)のmountコマンドでうまくいくのに、起動時はダメとか大変でした。そんなときは起動時にエラーを出力してきますので、メッセージしたがいとりあえずSkipして、dmesg等で何が悪いのかを調べます。
とりあえず、自分の場合はこれでうまくいくようになりました。

64GBのSDをつけましたので、ちょっと大きなものも試せそうです。(本気でやるなら、SATAのI/Fもっているので、そちらに繋いだ方がいいでしょう。)

2016年4月6日水曜日

Jetson TK1購入

さて、早速Jetson TK1が家に来ました。(なんかよくわからないけど、2月末に商社が偶然ある程度の数量を入手できたみたいで、まだ在庫がありました)



(机の上キーボード、マウスが散らかってますが、そのあたりは気にしないように)
ここからが、苦難の道の始まりです。ネットで色々設定方法を調べたのですが、どれも変わっており、どうしたらいいのか全然わからなくなりました。大きな問題が2つ。ホストPCとして、Ubuntu14のマシンが必要なのはわかっていました。(flashromに最新版のromイメージをUSB経由で書き込むのに必要)
しかし、最初にぶつかったのが以下の2つのトラブル。

①Jetsonが/etc/defaults/saneで問題があるといってきて、USBによる接続を拒否する。
 saneはスキャナーのIFらしく、どうもこれを使ってホストPCと接続しているようです。JetsonのDefaultではこれをnoにしてあり、viでyesにしてやる必要があります。(だったら、最初からyesにしておけよ!)
②romイメージの書き込み最中に、なにか127.0.,0.1:33335が開けないと怒られてとまる。
 これはだいたい想像がつきました。ホストPCはUbuntu64bitをセットアップしたばかりです。sshdがインストールしてありませんでした。単にインストールして終わり。

しかし、その後も全然設定ができません。そもそも、設定に使うtoolがぐぐったのと全然違います!進化の早いとこなので、しかたないにしても全然対応がわかりません。(どうやってもうまく行きません。(T_T))

散々、ぐぐった結果やはりJetsonのLinuxはぼろぼろだとのこと。grinch版がいいとのこと。そこで、それをROMに焼くことに決定。
まずはまっさらなUbuntu、L4Tをいれます。

  1. wget http://developer.download.nvidia.com/embedded/L4T/r21_Release_v3.0/Tegra124_Linux_R21.3.0_armhf.tbz2
  2. wget http://developer.download.nvidia.com/embedded/L4T/r21_Release_v3.0/Tegra_Linux_Sample-Root-Filesystem_R21.3.0_armhf.tbz2

展開して、ROMに書き込みます。

  1. tar -xvf Tegra124_Linux_R21.3.0_armhf.tbz2
  2. (中略)
  3. cd Linux_for_Tegra/rootfs
  4. sudo tar xpf ../../Tegra_Linux_Sample-Root-Filesystem_R21.3.0_armhf.tbz2
  5. cd ..
  6. sudo ./apply_binaries.sh

このあと、Jetsonをrecovery-modeで起動して、イメージを焼きます。(一応、同封してあるダンボールの紙にボタンの説明はありました。注意しましょう。当然、英語です)

  1. sudo ./flash.sh jetson-tk1 mmcblk0p1

これをやる前に、USBで接続されていることを、lsusbコマンドで確認。NIVIDIAが見えます。あと、本当ならdeviceとして、/dev/mmcblk0p1が見えるはずなんですが、自分の環境では見えませんでした。 ただ、一応これで書き込みはできました。 さて、ここからはJetson側で起動イメージの差し替えです。ネタは元にありますので、コマンドだけ羅列しておきます。

  1. wget http://www.jarzebski.pl/files/jetsontk1/grinch-21.3.4/zImage
  2. wget http://www.jarzebski.pl/files/jetsontk1/grinch-21.3.4/jetson-tk1-grinch-21.3.4-modules.tar.bz2
  3. wget http://www.jarzebski.pl/files/jetsontk1/grinch-21.3.4/jetson-tk1-grinch-21.3.4-firmware.tar.bz2
  4. sudo tar -C /lib/modules -vxjf jetson-tk1-grinch-21.3.4-modules.tar.bz2
  5. sudo tar -C /lib -vxjf jetson-tk1-grinch-21.3.4-firmware.tar.bz2
  6. sudo cp zImage /boot/zImage

ちょっと不親切ですみませんが、まあこの世界はこんなもんです。
結局、最新版のライブラリはTX1用だけで、TK1にはでていないようです。その後、以下のリポジトリを登録します。

  1. sudo apt-add-repository universe
  2. 'universe' distribution component enabled for all sources.
  3. sudo apt-get update
  4. sudo apt-get upgrade

何故か、g++がないので、個別にインストール。

  1. sudo apt-get install g++

これでやっとCUDAの開発用ライブラリをインストールできる準備ができました。(これまでのはあくまで準備作業です。おいおい、ってな感じですが先は長いです。)
さてやっと、CUDA-6.5のライブラリをインストールします。(最新は7.5ですが、7.0からARMのサポートがなくなったとのこと。TX1しか対応していない。どうするんだNVIDIA)


  1. wget http://developer.download.nvidia.com/embedded/L4T/r21_Release_v3.0/cuda-repo-l4t-r21.3-6-5-prod_6.5-42_armhf.deb
  2.  
  3. sudo dpkg -i cuda-repo-l4t-r21.3-6-5-prod_6.5-42_armhf.deb
  4. (中略)
  5. sudo apt-get update
  6. (中略)
  7. sudo apt-get install cuda-toolkit-6-5

これで、CUDA6.5までインストールできました。あとはGPUを使えるように、自分をvideoグループに登録し、PATHを通しておきます。

  1. sudo usermod -a -G video $USER
  2. echo "export PATH=/usr/local/cuda/bin:$PATH" >> ~/.bashrc
  3. echo "export LD_LIBRARY_PATH=/usr/local/cuda/lib:$LD_LIBRARY_PATH" >> ~/.bashrc
  4. source ~/.bashrc

うまくいけば、専用コンパイラのnvccのバージョンが確認できます。

  1. nvcc -V
  2. nvcc: NVIDIA (R) Cuda compiler driver
  3. Copyright (c) 2005-2014 NVIDIA Corporation
  4. Built on Tue_Feb_17_22:42:19_CST_2015
  5. Cuda compilation tools, release 6.5, V6.5.45

最後に、時間がUTCのままなので日本(Tokyo)にしておきましょう。

さて、Sampleを動かさないと、実感が湧きません。

  1. cuda-install-samples-6.5.sh

このコマンドがインストールされているはずです。これでHOMEにSampleがインストールされますから、そこでmakeします。結構時間がかかりますが、無事Sampleは動きました。昔だったらなんの計算に使おうかと考えますが、今はAIですね。まずはディスクの容量がFlashの16GBしかないので、これをなんとかしないと。

2016年3月31日木曜日

CUDAを試してみたい

何となく、CUDAを試してみたくなりました。
昔から興味はあったんですが、中々やってみる時間がなくて。。。 手近のPCでNVIDIAを積んでるマシンというと、WinXPの頃に買ったGame用PCがあります。ただ、GPUがちょっと古い!(GT-9800)NVIDIAのHP見てみると、一応対応はしているとのこと。

このPC、Ubuntuの32bitをインストールしてありますが、せっかくなので64bitをインストールして、CUDAをインストールしてみました。しかし、大失敗(-_-;) 画面の解像度は落ちて、ドライバはうまくインストールできたようなのですが、サンプルプログラムを動かすとなぜか「デバイスが掴めません」(意訳)みたいなことを言ってきて動きません。
実は、事前にnvidiaを積んでるMacBookAirでも試してみたんですが、そちらでもそんなことを同じサンプルプログラムで言われました。(T_T)

Ubuntuならいけるかと思ったんだが。。。しかし、問題はここからでした。CUDAをアンインストールできません。インストールは必要なものの塊をNVIDIAのHPからDLしてきましたが、アンインストール方法がどうしても見つからず、しかたなく関連しそうなものをひとつずつapt-get removeしたんですが、どうにも元に戻りませんでした。

あきらめて、Ubuntuを再インストールしてしまいました。(このPC、別の用途で古いUbuntu-10も入れてあったんですが、これを残すためにインストール方法はかなり苦労しました。何度かgrubを壊してしまいました)

やっと復帰して、このブログを書いているわけですが、まだ以前のUbuntu14の状態には戻せていません。そちらはおいおいやるとして、CUDAのためにJetson TK1をポチりました。こっちの専用マシンのほうが試すのにらくでしょうから。(今だったら、TX1だろうという声もあるかもしれませんが、あちらは気軽に試すにはちょっと勇気の必要な価格です。)

2016年2月21日日曜日

AWSを使ってみる:Deep-learningのために

このところ、Deep-learningの勉強をしているんですが、サンプルでとにかく処理時間のかかるものがあります。
chainerやTensorFlowは64bit環境が前提(chainerはそうでもないんですが、そっちのほうが望ましい)なので、自宅のLinuxは32bitでアウト。そうなるとMac OSXになるのですが、ノートPCなので電源つなげっぱなしはバッテリーへのタメージから考えると避けたい。
自宅のLinuxを64bitにしてもいいんですが(古いPCですが、Core2なんで一応64bit OSはインストールできます)、せっかくなのでAWSを試してみます。

お試しなので、作れるインスタスは小さな"t2.micro"になります。(64bit redhatですが、メモリが1GBしかありません)それでも、まあchainerは動くだろうと、インストールを始めますが色々問題が出ました。

1.rootのパスワードは何?
まず、pipをインストールしようとしたらエラーがでました。まあ、この手のものはroot権限が必要ですから、sudoコマンドを使おうとすると、passwdを聞かれました。でも、AWSでEC2にインスタンスを作ったばかり、passwdは何?最初、AWSのアカウントのパスワードかと思いましたが、初期状態ではpasswdが設定されていないので、

$ su -
$ passwd

で、rootのパスワードを設定してやるものなんだそうです。

2.chainerのインストールができない(gccが必要)
さて、pipのインストールができたので、それでchainerをインストールしようとすると、エラーがでます。はじめは何が問題なのかわからなく、色々ぐぐってみました。でもどれも見当はずれ。よくよくエラーメッセージをみると、gccコンパイラがないと・・・
そうです、AWS EC2のインスタンスでは最低限のものしか入っていなくて(でもpythonは入っていた)、gccがなかったのです。

$ sudo yum install gcc
$ sudo yum isntall gcc-c++  ←これわかり難い
$ sudo yum install gcc-gfortran ←これも通常の名前と違うみたい
$ sudo yum install python-devel  ←これが一番悩んだ。pipで、Python.hがないと怒られた。

と、いろんな開発用パッケージをインストールしないといけません。AWS内ではyumリポジトリがAmazon専用のものが設けてあるのは知っていましたが、なんかパッケージ名が違うのか?ググったものと”微妙”にパッケージ名が違い困りました。(何かパッケージ名が微妙に違う気がしますが、これは自分が数年間RedHatから遠ざかり、Ubuntuを使い続けたからかもしれません)

3.virtualenv環境でchainerが動かない
これはまだ原因がわかりません。上記、各種パッケージのインストールをしたあと、virtualenv環境下でchainerをインストールしたのですが、なぜかnumpy等のパッケージが見つからないと怒られます。しかたなく、virtualenvの使用をあきらめるとうまくいくので、色々試行錯誤してるうちにどこかで間違ったかもしれません。

と、かなりとまどいました。とりあえず、今回はここで力つきました。AWSでDeep-learningを試してみるのは次にします。

2016年2月20日土曜日

TensorFlowで学習プログラム

TensorFlowで学習するプログラムを作ってみました。
一番単純な、2入力1出力です。(論理積を学習させます)
以前、chainerとかのサンプルも探しましたがどれも学習結果を使う所が見つかりませんでした。TensorFlowだとダイレクトにプログラムしないといけないので、その辺りは楽にできました。

とりあえず、サンプルです。


  1. # -*- coding: utf-8 -*-
  2.  
  3. import tensorflow as tf
  4. import numpy as np
  5.  
  6. # 入力データの定義 4行2列(データの定義方法がchainerとは違うようです)
  7. # x_data = [
  8. # np.array([0., 0.]),
  9. # np.array([0., 1.]),
  10. # np.array([1., 0.]),
  11. # np.array([1., 1.])
  12. # ]
  13. x_data = np.array([
  14. [0., 0.],
  15. [0., 1.],
  16. [1., 0.],
  17. [1., 1.]
  18. ])
  19.  
  20. # 結果データの定義(4行1列)
  21. # y_data = [
  22. # np.array([0.]),
  23. # np.array([0.]),
  24. # np.array([0.]),
  25. # np.array([1.])
  26. # ]
  27. y_data = np.array([
  28. [0.],
  29. [0.],
  30. [0.],
  31. [1.]
  32. ])
  33.  
  34.  
  35. # 機械学習で最適化するWとbを設定する。Wは4行2列のテンソル。bは4行1列のテンソル。
  36. W = tf.Variable(tf.random_uniform([4, 2], -1.0, 1.0))
  37. b = tf.Variable(tf.zeros([4, 1]))
  38. y = W * x_data + b
  39.  
  40. loss = tf.reduce_mean(tf.square(y_data - y))
  41. optimizer = tf.train.GradientDescentOptimizer(0.5)
  42. train = optimizer.minimize(loss)
  43.  
  44. # 学習を始める前にこのプログラムで使っている変数を全てリセットして空っぽにする
  45. init = tf.initialize_all_variables()
  46.  
  47. # Launch the graph.(おきまりの文句)
  48. sess = tf.Session()
  49. sess.run(init)
  50.  
  51. # 学習を1000回行い、100回目ごとに画面に学習回数とWとbのその時点の値を表示する
  52. for step in xrange(1001):
  53. sess.run(train)
  54. if step % 100 == 0:
  55. print step, sess.run(W), sess.run(b)
  56.  
  57. # 学習結果を確認
  58. x_input = np.array([
  59. [0., 0.],
  60. [0., 1.],
  61. [1., 0.],
  62. [1., 1.]
  63. ])
  64.  
  65. y_res = tf.Variable(tf.zeros([4, 1]))
  66. y_res = W * x_input + b
  67. print sess.run(y_res)
  68. # 4行1列の結果を期待しているのだが、4行2列になってしまう?
  69. # 学習が十分進めば、どちらの列も同じような結果になるからいいか。
  70. print sess.run(b)

最後に、学習結果を確認しています。結果はこうなります。(一応、期待通りの結果になりました)
  1. [[ 0.00000000e+00 0.00000000e+00]
  2. [ -2.62142518e-23 1.62012971e-23]
  3. [ 7.70256410e-23 -1.24630115e-22]
  4. [ 9.99999881e-01 1.00000012e+00]]
  5. [[ 0.00000000e+00]
  6. [ -2.62142518e-23]
  7. [ -1.24630115e-22]
  8. [ 6.69862151e-01]]
最後の、変数y_resとbの出力だけを貼り付けました。 どうしてもまだ理解できないのが、y_resの計算結果は4行1列になるはずなんですが、4行2列になってしまいます。(代入する直前でy_resを4行1列で定義しても上書きされてしまいます。bは4行2列でも、4行1列でも構わないようです)ただ結果をみると各行の値はどちらの列をとっても同じような値なのでよさそうです。 まだ深層学習の理論的な本を買って読み始めた所でよくわかっていませんが、TensrFlowの方がPrimitiveにプログラムしなければいけない分、直感的にわかります。(でもなんとなく、chainerの方がこの後進めていくのによさげな気もしますので、しばらく悩みます)

2016年1月31日日曜日

Mac OSX El Capitanの日本語入力について

MacのOSX、El Capitanにしてみました。(いつも通り、しばらく様子を見ていました。brewとかなんだかんだ入れているので、いきなりは怖いです)

こちらはWindowsほど劇的な変化はありませんでしたが、使い勝手で一番戸惑ったのが「日本語入力」です。デフォルトが自動変換になってました。Google日本語入力でもありましたが、強力な予測変換で、ユーザーが変換の意思を「スペースキー」を押さなくてもいいようにしてくれるんですが、自分的にはこれ大嫌いです。

OSが勝手に漢字変換を、意図しないタイミングでしてしまうのと、その瞬間どうしてもPCの動きが止まります。よどみなくタイピングしている最中に、意図しない漢字変換されてしまうとものすごいストレスを感じます。もうすぐに「自動変換」をオフしてしまいました。
MSとかApple、Googleはこの辺どう考えているんだろう?仕事でPC使っている人間には、どう考えても今の予測変換の実装はマイナスにしかなりません。(まだ、ガラケーやスマホの予測変換みたに、別領域に変換候補がでてきて、ユーザーが必要ならそれを選ぶ方式なら我慢できますが、入力しているカーソル部分で強制的に第一候補を表示してしまうのは困る。)変換候補を別領域に表示、選択はファンクションキーがいいと思うんだが、どうなんだろう?日本語意外の他の「非英語圏」のUIはどんな使い心地なのか気になります。

windows10について

自分のメインPC(Core2 Quad win7 64bit)を何時かwin10にしないといけないと思いながら、タイミングを計ってきました。他のPCは特に考えずに適当に更新をトライしてましたが、こいつだけは銀行のHP見たりするヤツなんで慎重です。
win10も発表から何度かUpdateがされ、金融機関から最初は出ていた更新を待ってくれという警告もなくなったので、そろそろ試してみるかとやってみました。

最初に感じたのが、とにかく時間がかかること!まあ、OSのメインバージョンの更新なんだから、当たり前なんですが問題は更新後です。
自宅のPCで、EPSONのノートPC(Win7)がWin10に更新できませんでしたが(最後に問題が発生しました。HDDのパーティションの切り方が特殊なようです)、プリンタ・スキャナのドライバが最初は対応してくれず、ドライバの再登録などして何とか使えるようになりました。
後、更新後しばらくは「無茶苦茶遅い!」と感じました。Win10にしたら快適になると聞いていたんですが、「ダメじゃん」という感じ。調べてみると、暫くの間は「自動メンテナンス」で調整をする時間が必要なようです。数時間から1日くらいPCの電源入れっぱなしにして、MSとデータ交換しないといけないようです。

また、安定しても基本認証にMSとインターネットで通信しまくる仕様のようで、パフォーマンスモニタとか見てると、いつもネットワーク通信しています。そうそう、PCへのログイン・アカウントがそれまでのから、強制的にMSのアカウントに切り替えられてしまいました。(設定の途中で、MSのアカウント入力をさせる箇所があり、そこで入力してしまったせいでしょう)これではネットワークがない状況だとどうなるんだろう、という感じです。(最初から、ネットワークなしの状況で設定してればいいんでしょうが、一旦ネットワークがある状況で設定してしまうと、その後はタイムアウト待ちをするしかない?)

前回のWin8がひどい出来だったので、ほとんどWin7の操作に戻った感じですが、全体的に「常時オンライン」が前提のOSになってしまったようです。これはこれで、鬱陶しい!反応が鈍くなるんですよ。しかし、セキュリティの事を考えたらWin10に更新せざるをえません。付き合い方を考えるしかありませんね。

後、困ったのがウイルス対策ソフトのDefenderです。Google Drive等からファイルをDLすると自動的にスキャンしているようなんですが、時間が10~20秒くらいかかり、その間ファイル名の変更ができません。(Defenderがファイルをつかんでいるから)ちょっとこれにはまいりました。何とかなりませんかね。(時間がかかりすぎ。もしかしてパターンチェックか、データをMSに送っているのか?)

2016年1月6日水曜日

python:virtualenvメモ

ここのところchainer, TensorFlowとpythonを使ってみることが多かったのですが、他の方はよく

$ virtualenv

というコマンドを使って、そこに環境を構築していました。名前からすると「何らか」の仮想環境を構築するものなのでしょう。ちょっと調べてみると、python専用のライブラリを「試しで」作るときに、メインの環境にダメージを与えないようにするものでした。要は、VMwareやDocker(こっちの方が間隔的に近い)の様な仮想環境ですが、python限定なのが特別です。(ただ、試しにやってみたら、頑張れば、その中でのみ連携して動くJavaやc++のライブラリ、プログラムも入れれそうな感じです。ただ、Javaやc++のライブラリが特別な別のパッケージを要求していると、かなり大変そう。)

1.インストール
pipコマンドが使えるようになっているなら簡単です。

$ pip install virtualenv

これだけです。(中身は10行くらいのpythonスクリプトです)

2.仮想環境の構築
以下のコマンドだけです。

$ virtualenv testenv

これで、testenv/というディレクトリが作成され、配下に以下のディレクトリが作られます。

bin/ include/ lib/ local/

ここに当該OS環境におけるpython環境がコピーされてきます。(後で追加したpackage等は入っていません。使いたい場合はここで再構築です。)

3.仮想環境の実行
この環境でpythonのあるpackageを試してみたくなったら、以下の手順になります。

$ cd testenv
$ source bin/activate

この"activate"は先ほどコピーされたbin/以下に入っており、これを実行することにより、pythonバイナリ、ライブラリはtestenv/以下のものを参照するようになります。(プロンプトにtestenvの文字が追加され、仮想環境下で動いていることがわかります)
つまり、この環境下で"pip"コマンドでインストールすると、testenv/以下にインストールされることになり、本体OSのpythonには影響を与えません。

4.仮想環境の終了
以下のコマンドです。

$ deactivate


5.仮想環境の削除
お試しが終了して、必要なくなったらディレクトリ毎削除すればOKです。

$ rm -rf testenv/


と、非常にお手軽に色々なpythonのパッケージを試すことができます。