ぱたへね!

はてなダイアリーはrustの色分けができないのでこっちに来た

rustでマクロ

rust standard library cookbookから。

マクロを使って、簡単な可変長引数を実現する例。

macro_rules! multiply {
    ( $last:expr ) => { $last };

    ( $head:expr, $($tail:expr), + ) => {
        $head * multiply!($($tail), +)
    };

}

fn main()
{
    let val1 = multiply!(2, 4, 8);
    println!("2 * 4 * 8 = {}", val1);

    let val2 = multiply!(2, 4, 8, 16);
    println!("2 * 4 * 8 * 16 = {}", val2);
}

マクロの中で再帰するのか。すごいな。

Rustでグラフ

ほとんどライブラリの使い方レベルだけど、なんとか動いた。

extern crate petgraph;

use std::fs;
use std::io::Write;

// https://docs.rs/petgraph/0.4.13/petgraph/
use petgraph::Graph;
use petgraph::algo;
use petgraph::dot::Dot;

fn main() {

    let mut graph = Graph::new_undirected();
    let na = graph.add_node("a");
    let nb = graph.add_node("b");
    let nc = graph.add_node("c");
    let nd = graph.add_node("d");
    let ne = graph.add_node("e");
    let nf = graph.add_node("f");

    graph.add_edge(na, nb, 20);
    graph.add_edge(nb, nc, 20);
    graph.add_edge(nc, nd, 10);
    graph.add_edge(na, ne, 10);
    graph.add_edge(nb, ne, 10);
    graph.add_edge(nb, nf, 30);
    graph.add_edge(nd, nf, 10);
    graph.add_edge(ne, nf, 20);

    let mut f = fs::File::create("graph.dot").unwrap();
    let dot_str = format!("{:?}", Dot::with_config(&graph, &[]));
    f.write(dot_str.as_bytes()).unwrap();

    let path = algo::dijkstra(
        &graph,
        na,
         Some(nd),
        |e| *e.weight()
    );
    println!("result: {:?}", path);
}

実行結果

f:id:natsutan:20181019131430p:plain

なんとなく動いているっぽい

result: {NodeIndex(1): 20, NodeIndex(5): 30, NodeIndex(0): 0, NodeIndex(3): 40, NodeIndex(4): 10, NodeIndex(2): 40}

久しぶりにKerasを動かしたときのメモ

import keras しただけでこういうエラーがでる。

ImportError: libcublas.so.9.0: cannot open shared object file: No such file or directory

libcublasが見つからないだけなので、.bashrcにLD_LIBRARY_PATHを追加する。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-9.0/lib64/

ターミナルから動いてPyCharmで同じエラーが出る場合は、PyCharmのrun configurations(working directoryとかを設定する画面)から、Environmet variables に上のLD_LIBRARY_PATHを追加する。

TVMで使われている最適化の探索手法

TVMとは

ペーパーはこちらからダウンロードできます。 https://arxiv.org/abs/1802.04799

TVMは、ASICやAPGAの様な組込様CPU等、様々なバックエンドでDeep Learningを動かすことを目的としたコンパイラです。 グラフレベルや演算子レベルの様々な最適化を行います。

興味本位でペーパーを読んでみたら、僕の知らない最適化テクニックが使われていたので紹介します。 他にも面白いことは書いてあったのですが、最も気になった2つを紹介します。

TVM stack

f:id:natsutan:20181013084651p:plain

TVMは図のようなスタック構造になっています。上から順番に最適化をしていって、最後にLLVMやCUDAのソースコードを生成します。High level Graph Rewritingの話(Section 3)や、Tensorとスケジューリングの話(Section 4)で最適化した後、それらの組み合わせを考慮するときに、機械学習を使って最適化をしています。

TVMは、このOptimizerに来る前に可能な限りの最適化を考えます。その結果、10億以上の最適化の組み合わせ(configuration)から、実際のワークロードに適した組み合わせの検索をOptimizerが行います。つまり 、Optimizerは実際に最適化をするのではなく、最適化の組み合わせの探索に機械学習を使っています。

ML based Cost Model

最適化の探索には、様々なファクターがあります。 - メモリアクセスパターン - データの再利用 - パイプラインの依存性 - スレッドのパターン - etc 最適化のするに当たっては計算のコストモデルを作る必要があります。 従来のAuto-turningの手法では良い組み合わせを探すのに多くの実験が必要になります。定義済みのコストモデルを使う場合は、バックエンドのハードウェアへの依存性が高くなります。そこでTVMでは、機械学習を使ったアプローチを取っています。

f:id:natsutan:20181013084809p:plain

図のように、ループの構文ツリーをTreeRNNに入れ、特徴量を出しコストを予想しています。

Schedule Exploration

コストモデルが決まった後は、そのコストモデルに従って一番良い組み合わせを探します。理想的には全てのコンフィグレーションを試し上位のいくつかを選択すれば良いのですが、それには強大な探索空間が必要になります。その問題を解決するために、TVMは a parallel simulated annealing algorithmを使います。

まずはランダムに選んだコンフィグレーションから開始し、ランダムウォークをしながら、コストモデルが予測するコストが低い方へ移動していきます。ランダムウォークはコストの低いところを見つけ、移動しなくなるまで続けられます。

感想

コンパイラの最適化技術がここまで進んでいるとは思いませんでした。個別のターゲットに対して、個別の最適化を行う時代は過ぎているだと思います。AIによって世界中の誰でも、どのデバイスでも、最適化職人の技術の恩恵にあずかれると思うと素晴らしいですね。

コンパイラ勉強会が来月に開催されるようで、申し込んではみましたが抽選に通るかどうか難しいそうです。 https://connpass.com/event/103976/

Rustで文字列の連結

Rust Standard Library Cookbookを読み始めました。

Amazon CAPTCHA

この本ではRustの文字列連結として3つの方法が紹介されています。

moveによる連結

一番標準の方法。わかりやすく効率も良いが、連結後はmoveによりhelloは使えなくなる。

fn by_moving() {
    let hello = "hello ".to_string();
    let world = "world";

    let hello_world = hello + world;

    println!("{}", hello_world);
}

helloはStringで、worldが&str。この2つを連結するとStringになるというのもよくわかってない。(なんで to_string()が必要なの?)

cloneによる連結

clone()を使うことで、一時変数が作られ、それをmoveすることで文字列を連結している。連結後もhelloが使えることがポイント。

fn by_cloning() {
    let hello = "hello".to_string();
    let world = "world";

    let hello_world = hello.clone()  + world;
    println!("{} ", hello_world);
}

mutingによる連結

helloをmutableで宣言して、push_strを使う方法。エレガントじゃないらしい。

fn by_mutating() {
    let mut hello = "hello".to_string();
    let world = "world";

    hello.push_str(world);
    println!("{} ", hello);
}

今まで勉強したプログラミング言語の中で一番文字列がめんどくさい。

元のソースはこちらです。 github.com

GCPUG in Osaka #8【GCP】〜 Google TPU Day 〜


マーチンのおっかけで、GCPUGへ参加してきました。
https://gcpug-osaka.connpass.com/event/100106/

Tensorflow and modern convnets グーグル Martin Görner さん・吉川さん

Google martinによる。最新のコンボリューションネットワークの紹介。CNNの基本から始めて、inception modelやsquuzenet等、最近の画像系ネットワークに関して、さわりの説明がありました。

デモは飛行機検出のデモでした。京都とは違う確度から説明されていて、ハイパーパラメータのチューニングに関するトピックもありました。基本はアイデアをいくつか実装してGCPを使って一気に動かすこと。お金持ちの発想の気がします。

複数のハイパーパラメータから最適な物を探すときには、グリッドサーチでは無くランダムに振った方が良い。ただし、いろいろとハイパーパラメータを振る前に学習を安定させるのが大事と。飛行機の例だと、ハイパーパラメータを降る前にデータオーギュメンテーションを行って、学習が安定(曲線がなだらかに)してから、いろいろ振った方が良いみたいです。

TPUに関しては、安くて速い、使わないと損という感じの猛プッシュでした。200円ネタを外したのは残念。おもしろいのに。

BigQueryネタ [Cavity LLC.](http://www.cavity.jp/) 中田 さん

京都でも聞いたBigQueryネタ。正直、名前しか聞いたことが無いが、これだけ話題になるんだからすごいんだろうと思う。Googleさんが、こういうサービスのアイコンを公開して好きに使っていいよ〜ってやってたのが、勉強会で良い効果がでているなと感じました。

Firebase x スマートスピーカー x GCF がおまる さん

https://www.amazon.co.jp/dp/479805481X/

スマートスピーカーの本争奪じゃんけん大会がありました。今手が出せないから参加しなかったのですが、大阪の開発メンバーなら喜んでくれそうで、参加すれば良かったと後悔。社内で紹介しておこう。

最後に

GCPUGに初めての参加でしたが、とても楽しめました。GCPUGのみなさん、会場を提供いただいたGMO様、ありがとうございました。

DevFest Kyoto 2018 & TPU

日曜日にDevFest Kyotoに参加してTPUの情報を集めてきました。
https://gdgkyoto.connpass.com/event/99527/

Twitterでは見たことがあるこの図を生で見れたのが良かったです。

TPUで使用されているbfloatフォーマットについて。

よく見ると、指数部を増やして、仮数部を減らしています。推論で使うことを考えると、適切な正規化を行うことでデータの範囲をある程度制御でき、むしろ指数部が要らない気がします。となると学習時の勾配をハンドルするために、指数部を増やしていると思います。学習に関しては、最初はbflot16で進めて、learning rateを下げるタイミングでfp32に切り替えたりしたら、速度と精度のバランス取れそうです。妄想が膨らみますね。

消費電力について

TPU v3の消費電力はシークレットという事ですが、水冷が必要になっている時点でお察し案件だと思います。TPU v2について上から見た写真しかなく、横から見た写真が公開されていないのは、放熱器の大きさからだいたいの消費電力がばれるからだと思います。
僕の勝手な予想だと両方とも100Wくらいあるのではと思います。

発表資料

マーチンのTPU発表資料はこちらです。
https://docs.google.com/presentation/d/1iodAZkOX0YMnUwohgQqNsbEkhR0zAnO-jncK9SkJ69o/edit

お礼

すごく楽しいイベントを企画していただき、運営の方々ありがとうございました。
Lispの人にも挨拶できなかったのが気がかりです。たまに使ってますよLisp