ぱたへね

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

GCPでTPUを動かしたメモ

GCPでTPU動いたのでメモ

準備

ここ読みながらTPUを起動する。ctpu upの前に、ブラウザのコンソールからSTARTさせないと動かなかった。(TPUにチェックを入れて緑色になっただけだと動いていなかった。)

https://cloud.google.com/tpu/docs/quickstart?hl=ja

途中でshellが変わって補完が効かなくなったのがつらい。まだよくわからない仕組みで動いている。

ちなみに、TPU使うだけならGPUインスタンスの契約は不要。GPU無しのVMとTPUだけ契約すればOK。TPUをプリエンプティブにするとそんなにお金はかからない。12月中はそこそこ遊んだけど、まだ10ドルもかかってないです。

ソース

TensorFlowが良くわからないのでKerasで。

import os
import tensorflow as tf
from tensorflow.contrib import tpu
from tensorflow.keras.datasets import mnist
from tensorflow.keras import layers
from tensorflow.keras import models
from tensorflow.keras.utils import to_categorical

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# (60000, 28, 28)
#print(train_images.shape)

# (10000, 28, 28)
#print(test_images.shape)

network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
network.add(layers.Dense(10, activation='softmax'))

# loss function
# optimizer
# metrics

network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

# normalization
train_images = train_images.reshape((60000, 28*28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28*28))
test_images = test_images.astype('float32') / 255

# one hot encoding
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

tpu_grpc_url = tf.contrib.cluster_resolver.TPUClusterResolver(tpu=[os.environ['TPU_NAME']])

strategy = tf.contrib.tpu.TPUDistributionStrategy(tpu_grpc_url)

tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    network,
    strategy=strategy
)

tpu_model.fit(train_images, train_labels, epochs=5, batch_size=128)
test_loss, test_acc = tpu_model.evaluate(test_images, test_labels)

tpu.shutdown_system()


# test_acc: , 0.9786
print("test_acc: ,", test_acc)

結果

natsutan0@emiru:~/myproj/keras_book/chap2$ python3 mnist_tpu.py
WARNING:tensorflow:From /home/natsutan0/.local/lib/python3.5/site-packages/tensorflow/python/ops/resource_variable_ops.py:434: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be rem\
oved in a future version.
Instructions for updating:
Colocations handled automatically by placer.
2018-12-25 02:02:07.817964: W tensorflow/core/distributed_runtime/rpc/grpc_session.cc:354] GrpcSession::ListDevices will initialize the session with an empty graph and other defaults because the session has no\
t yet been created.
WARNING:tensorflow:tpu_model (from tensorflow.contrib.tpu.python.tpu.keras_support) is experimental and may change or be removed at any time, and without warning.
2018-12-25 02:02:07.834462: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2500000000 Hz
2018-12-25 02:02:07.834760: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x55f1d962b4d0 executing computations on platform Host. Devices:
2018-12-25 02:02:07.834798: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): <undefined>, <undefined>
Epoch 1/5
WARNING:tensorflow:From /home/natsutan0/.local/lib/python3.5/site-packages/tensorflow/contrib/tpu/python/tpu/keras_support.py:302: to_float (from tensorflow.python.ops.math_ops) is deprecated and will be remov\
ed in a future version.
Instructions for updating:
Use tf.cast instead.
WARNING:tensorflow:From /home/natsutan0/.local/lib/python3.5/site-packages/tensorflow/python/ops/math_ops.py:3064: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future v\
ersion.
Instructions for updating:
Use tf.cast instead.
WARNING:tensorflow:Cannot update non-variable config: epsilon
60000/60000 [==============================] - 8s 140us/sample - loss: 0.2546 - acc: 0.9275
Epoch 2/5
60000/60000 [==============================] - 4s 69us/sample - loss: 0.1038 - acc: 0.9697
Epoch 3/5
60000/60000 [==============================] - 4s 71us/sample - loss: 0.0680 - acc: 0.9797
Epoch 4/5
60000/60000 [==============================] - 4s 71us/sample - loss: 0.0486 - acc: 0.9853
Epoch 5/5
60000/60000 [==============================] - 4s 71us/sample - loss: 0.0365 - acc: 0.9890
10000/10000 [==============================] - 4s 355us/sample - loss: 0.0795 - acc: 0.9751
test_acc: , 0.9751
natsutan0@emiru:~/myproj/keras_book/chap2$

TPUが起動していない時はTPU無いで~って怒られる。それがでなくなったのでなんか動いてると思う。 さすがにこの規模だとCPUに比べて気持ち速いレベルです。もうちょっと大きなモデルでやってみたい。

rustで細かいプログラムを一つのディレクトリに入れる

なんかタイトル何ってるかわかりにくいです。

rustでプログラムを作るときは、cargo newコマンドを使います。ただ、ちょっとしたプログラムを作る度にcargo newするのも面倒ですよね。ディレクトリもどんどん増えますし。本で勉強していて、練習問題がでてきたとき、問題一つ一つにディレクトリを作るよりは、chapter1みたいな形でまとめたい。

cargo newしたディレクトリで、複数のソースと実行環境をまぜる方法です。

まずは、cargo new します。

cargo new --bin chap1 

簡単に動作確認をします。

cd chap1
cargo run

これでhello worldが表示されます。

次にcargo newで作られたsrcの下にbinディレクトリを作ります。そこに例えばfirst.rsといったソースファイルを書きます。

fn main() {
    println!("Hello, world first!");
}

この状態で、cargo runにオプションを与えると、first.rsをコンパイルして実行します。

cargo run --bin first

こうすると自動で作られたmain.rsではなく、先ほど作ったfirst.rsがコンパイルされ実行されます。

以後、src/binの下にsecond.rs, third.rsを作り、cargo runのオプションでソース名を指定することで狙ったプログラムだけが動きます。

ちょっとしたプログラムを書くときは便利です。

The RISC-V Reader: An Open Architecture Atlas

パターソン先生の動画を見て、これは読まねばならぬと思い読んでみました。

https://www.amazon.com/RISC-V-Reader-Open-Architecture-Atlas/dp/0999249118/

Amazon.co.jpでは取り扱ってないけど、.comでは普通に買えます。不当に高いのをつかまないように。

プロセッサ大反省会の乗りで楽しく読めました。命令セットの説明も結構取ってあります。読むところのボリュームはそれほど多くないです。RISC-Vプログラマでも無い限り、細かい命令セットを覚えてもしょうが無いので、面白いところだけ読めば良いかと。

面白いのは設計上の判断するにあたって、どういう観点で判断したのかが明確になっています。

  • cost
  • simplicity
  • performance
  • isolation of architecture from implrementation
  • room for growth
  • program size
  • case of programming / compiling / linking

こういう話は開発者の中で閉じていて、外部にストレートに出てくることは少ないので勉強になりました。

20年くらいたったら、貴重な資料になりそうです。全てのプロセッサ好きにお勧めです。

GCPでTPUを使えるようにする

GCPでTPUを使いたくて試行錯誤した途中経過です。

コンソールからの登録

GCPコンソールの左上からTPUを登録しようとしても、なかなか上手く行かず挫折。 結局 ip address rangeに何を入れて良いのか分かりませんでした。

ctpuコマンドを使う

ctpuコマンドをCloud shellから使う方法で上手く行きました。最初はctpuコマンドが使えなかったのですが、TPUのチュートリアルをこなしたところ、いつの間にか使えるようになってました。

gcloud config set compute/zone asia-east1-c
gcloud config set compute/region asia-east1

ctpu up -name emiru -preemptible true

ctpuコマンドが使えるようになれば、ゾーンとリージョンを指定してctpu upでTPUノードが登録されました。

京都Devかふぇ#4 〜レガシーシステム考古学〜

京都Devかふぇ#4 〜レガシーシステム考古学〜にLT参加してきました。

僕の発表資料です。

どの人の発表もすごく面白かったです。

レガシーコードとの戦いの軌跡

レガシーから脱出するために、レビューにきっちりと時間を取って、ちゃんと管理しているのがすごいと思いました。 リーダブルコードは良書なのでぜひみんなに読んでもらいたいです。

iPhone OSアプリ開発の昔話

「脱獄」って最近聞かなくなりましたね。って所だけ理解できました。 なんだかんだ言って、開発者とユーザーに必要な機能、環境が少しずつ整備されている感じかなと。

データセンターの話

IDEってFPGA直結できるから好きなI/Fなんですが、めちゃくちゃレガシー扱いされていて泣いた。 レガシーを包み込むための仮想化技術の使い道が面白かったです。

fmty さん

レガシーなコミュニケーションツールの話。 同じような悩みをかかえていて笑いました。 複数で編集できるようにGoogle spreadsheetを提案したけど、結局Excelに戻った悲しさを思い出しました。最近のサービスってIEが対象外だったりするので、MSさんには責任をもってIEを駆逐して欲しいです。

takey さん

VB6まだまだ現役。定年の引き上げの流れの中、VB6もまだまだ生き残ると思います。 昔のVB6アプリケーションがそのまま動く、マイクロソフトとインテルの頑張りはもっと評価されて良いと思います。

mkashima さん

Windows95の愛されっぷりが良く分かるLTでした。 プレゼン資料の作り込みがすごかった。 brew cask でwindowsがインストールできるぞ!twitter.exeもあるぞ!

最後に

フリューさんってどこかで聞いた会社だと思ったら、アンチェインブレイズの会社じゃないですか。 まさかのアンチェインブレイズ遊んだ人とリアルで話す事ができました。次は開発した人に会いたいですね。 続編期待しています!

Rustの配列操作メモ

Rust Standard Library Cookbook から、気になった配列の操作をメモしました。

要素の取りだし

配列の要素を取り出すにはgetを使います。Option型で返ってくるので、Someかunwrapでその値を取り出せます。[ ]でも同じ動きです。

[ ]を使って配列の領域外にアクセスした場合は、回復できないので実行時エラーとなります。

    //配列要素の取り出し
    let cpus = vec!["sh", "x86", "arm", "mips"];

    //getで取り出す。
    let second_cpu = cpus.get(1);
    if let Some(second_cpu) = second_cpu {
        println!("second spu = {}", second_cpu);
    }

    //unwrap
    let last_cpu = cpus.last().unwrap();
    println!("last_cpu = {}", last_cpu);

    //no check
    let first_cpu = cpus[0];
    println!("first cpu = {}", first_cpu);

    //error
    //let cpu = cpus[10];
    //println!("cpu = {}", cpu);

重複の削除

dedup()を使うと、連続する重複する要素が1つにまとめられます。完全に重複を無くしたい場合は、sort()してから、dedup()を使います。

    //重複の削除
    let mut nums = vec![1, 2, 2, 2, 3, 3, 4, 5, 1, 5];
    nums.dedup();
    println!("deduped {:?}", nums);
    // deduped [1, 2, 3, 4, 5, 1, 5]

    let mut nums = vec![1, 2, 2, 2, 3, 3, 4, 5, 1, 5];
    nums.sort();
    nums.dedup();
    println!("deduped {:?}", nums);
    //deduped [1, 2, 3, 4, 5]

分割と結合

split_off()で分割して、append()で結合します。所有権も上手くやってくれます。

    let mut cpus = vec!["sh", "x86", "arm", "mips"];
    let mut later = cpus.split_off(2);
    println!("cpus = {:?}, later = {:?}", cpus, later);
    //cpus = ["sh", "x86"], later = ["arm", "mips"]

    cpus.append(&mut later);
    println!("cpus = {:?}, later = {:?}", cpus, later);
    //cpus = ["sh", "x86", "arm", "mips"], later = []

retain

配列から特定の要素だけを取り出します。何気に破壊的操作です。

    //retain
    let mut cpus = vec!["sh", "x86", "sh2", "sh4", "arm", "mips"];
    cpus.retain(|name| name.starts_with("sh"));
    println!("cpus = {:?}", cpus);
    //cpus = ["sh", "sh2", "sh4"]

drain

配列から要素を取り出したら、そのまま削除して欲しいときに使います。キュー的なアルゴリズムで活躍しそうです。

下の例は、配列cpusから先頭から二つを取り出して何かに使った後、取り出した分だけが配列から削除されます。

    //drain
    let mut cpus = vec!["sh", "x86", "sh2", "sh4", "arm", "mips"];
    for cpu in cpus.drain(..2) {
        println!("use {}", cpu);
    }
    println!("cpus {:?}", cpus);
    //cpus ["sh2", "sh4", "arm", "mips"]

swap_remove

Rustっぽい面白い操作です。通常、配列から要素を一つ削除すると、削除した後の要素をコピーして空白を埋める必要があります。swap_removeを使うと、削除した場所に最後の要素を入れて配列の大きさを一つ小さくすることで、要素のコピーを防ぎます。

下の例では、2を取り出して削除した後、空いた場所に配列の最後の要素6を入れることで、配列のコピーを防いでいます。

    let mut nums = vec![1, 2, 3, 4, 5, 6];
    let second_num = nums.swap_remove(1);
    println!("nums = {:?}, second_num = {}", nums, second_num);
    //nums = [1, 6, 3, 4, 5], second_num = 2

組合せ最適化アルゴリズムの最新手法―基礎から工学応用まで

組合せ最適化アルゴリズムの最新手法―基礎から工学応用までを読みました。

80年代後半、90年代の論文がよく出てきており、20年前の最先端をまとめた本です。題材に半導体関連のネタが多く、興味を持って最後まで読めました。シミュレーティド・アニーリング手法(SA)、遺伝的アルゴリズム(GAs)、タブー・サーチ手法(TS)、シミュレーティド・エボリューション手法(SimE)、確率的進化手法(StocE)について分かりやすく書いてありました。 ただ、この本を読んで実際の問題を解けるかどうかといわれると難しい気がします。

組み合わせ最適化について

この本にのっているアルゴリズムは、基本的にはすべてこのような手順になっています。

  • 上手い初期値を設定する
  • 上手く少しだけ良い方向へ変化する
  • 上手く局所解を抜けて、大域解へ向かう。

局所解を抜けるために、どこかで乱数を使います。各アルゴリズムの違いはどこを重視するかです。 遺伝的アルゴリズムであれば、初期値を大量に作り生き残りを作っていくことで、上手い初期値としています。 タブーサーチ方では上手く良い方向へへの変化を求めるときに、過去の失敗をタブーとして参考にします。

直行している概念も多く、最後の章ではそれぞれの組み合わせの考察もありました。

実際はこのアルゴリズムにかける前に、上手いモデルの定義があって、それはそれで見るからに面倒でした。上手く行った事例が結構載っているのですが、それ以外は上手く行かなかったんだろうなという感じです。

並列コンピューティングやSIMDへの期待が高いのも興味深く読めました。

当時のニューラルネットワークの評価

面白いことに半導体の配置問題をニューラルネットワークを使って解くという89年の取り組みが紹介されています。30年前のニューラルネットワークの評価として貴重な資料です。

本の中では、このようにまとめられています。

ホップフィールド型ネットワークを配置問題に適用したユーの結果は、有望なものではなかった。いくつかの問題点は、シミュレーション時間が長いこと、解の質が低いこと、および、ネットワークのパラメータに対して、解の感度が高いことである。現段階では結論として、ニューラルネットワークを困難な最適化問題にてきようできるかどうかについては、さらに多くの研究が必要であると、述べるにとどめる。