KZKY memo

自分用メモ.

Python: TCP Server

基本

Cのsokcet programmingとほとんど同じ

Server側

  • create socket
  • bind socket to (host, port)
  • socket listens with qsize
  • socket accepts connection
  • socket recv msg from a client
  • socket send msg to a client

Client側

  • create socket
  • socket connects to a server
  • socket send msg to a server
  • socket recv msg from a server

Workerを使う

シングルスレッドだと処理が重いので,Workerプロセスを使う

Main process

  • create socket
  • bind socket to (host, port)
  • socket listens with qsize
  • pass socket to child process

Child process

  • socket accepts connection
  • socket recv msg from a client
  • socket send msg to a client
  • msgを処理したらconn.shutdown, conn.close

今回はこうしているだけで,connを切らない方がいい場合もある.

コード

TCP Server

Python: Manager

基本

何ができるか

Manager は別のプロセス間で共有されるデータの作成方法を提供します。マネージャオブジェクトは 共有オブジェクト を管理するサーバプロセスを制御します。他のプロセスはプロキシ経由で共有オブジェクトへアクセスすることができます。

Managerは,

  • 共有オブジェクトを管理するサーバプロセス
  • 他のプロセス(over network)はプロキシ経由で共有オブジェクトにアクセス可能

という機能を機能を提供するといえる.

serverもclientもmanager classは作るが,

  • sever側は,manager.get_server().serve_forever()
  • client側は,manager.connect()

ManagerがSyncManagerのaliasになっていて,Localで基本的な共有オブジェクトを提供しているので,自分で作成したcallable object (とか)を使わないなら,Managerを使っておけばいい.ただし,Managerは引数を取らないので,引数を指定する場合は,SyncManager.分散前提なら,BaseManagerを拡張した独自,Managerを作った方がいい.

あくまで,共有オブジェクトを管理管理するサーバであるので,中央集権的な感じだろう.

なので,pythonで中央主権的な(簡易)分散システムを作成するなら,Managerを使えばいい.

コード

Manager Sample

Tensor Flow: Whitepaper

TensorFlow Whitepaperを2015/11/17に読んだ時のまとめ

Abstract

  • いろんなデバイスで動く
  • モバイイルから
  • 大規模GPU Clusterまで
  • Apache2.0 Licence

1 Introduction

  • DistBeliefは第1世代
  • TensorFlowは第2世代
  • TensorFlowのアブストラクションはdeep learningだけでなくて他のML, 数値計算に使える

2 Programming Model and Basic Concepts

  • ノードが可能な挙動はNaiadに似ている
  • その挙動は
    • 状態を保つ
    • 状態の更新
    • 状態の永続化
    • ブランチング
    • ルーピング
  • ノード
    • 0 to nのインプットをとれる,およびアウトプットを出せる
    • operation (実際の計算のこと)を行う
  • エッジ
  • スペシャルエッジ (control dependency)
    • このエッジのソースノードまでの実行はこのエッジのディスティネーションノードの実行より先に行わなければならない
    • ordering enforcementに使える

Operations and Kernels

  • operationはabstract computation
  • kernelはdevice (cpu, gpu, e.g., intel, arm, cuda, opencl, 実例はこれだと思う)上のoperationの実装

Session

  • セッションのなかでグラフ作って実行したりする
  • 基本この中でrunする

Varialbe

  • persistent stateをもつ
  • (パラメータありの演算ノードと思っておけばいい)

3 Implementation

Devices
  • Workerは1以上のdeviceに対して責任を追う

3.1 Single Device Execution

  • グラフノード上における実行順序の説明
  • 依存関係をカウントしておく
  • A -> B, A -> Cの依存だとAのカウントは2
  • Bが実行されたら,Aのカウントは1にディクリメントされる
  • カウントが0になったら実行queueに入れる
  • 実行queueのにある要素の取り出し順序は不定

3.2 Multi-Device Execution

3.2.1 Node Placement
  • グラフが構築されると,computationはset of devicesにマップされる
  • このマップするアルゴは(経験から求めた)コストベースで,絶賛検討開発中
3.2.2 Cross-Device Communication
  • メモリ最適化のために,依存関係が複数ある場合におけるreceive nodesの数が1つになるようにしている.(参考ダイアグラムはwhite paper参照)
  • 違うデバイス上のグラフノードのスケジューリングはworkerの責務で,マスターにさせない,マスターはrunリクエストを発行するのみ.

3.3 Distributed Execution

  • send/recieve nodesのコミュニケーションはTCPとかRDMA
Fault Tolerance
  • failureの判断は
    • send/recieve nodesのコミュニケーションの失敗
    • master to workerのhealth check.
  • faiureすると,初めからやり直しだけど,checkpointがあるとそこから再開

4. Extensions

4.1 Gradient Computation

  • automatic gradient computationはサポートしている
  • gradientは
    • operationに登録されてるときもある(基本されていると思う)
    • backward時の前ノードの微分とオプションとして,forward時の自分自身への入力および自分からの出力をインプットとする
  • automatic gradient computationはメモリ最適化を難しくするが,今頑張って改善使用としている.e.g., tensorをretainよりrecompute, long-lived tensorgpu mem to gpu memなど.

4.2 Partial Execution

  • run methodはsubgraphの実行も可能
  • graph 途中からデータを入れるも可能
  • graph 途中のデータを取り出すことも可能

4.3 Device Constraints

どのnodeをどのdeviceで計算を実行させるか可能

4.4 Control Flow

以下のコントロールが可能

  • cyclic dataflow graph
  • swith/mergeで,subgraphの実行をskip
  • enter/leave/next iterationでiteration
  • if-conditionals/while-loops

4.5 Input Operations

  • filenamesを受け取って,tensorを返す,input nodeの設置

4.6 Queues

ユースケース

  • input data prefetch
  • gradientsをグルーピングして,その複雑なコンビーネーションを計算する
  • RNNにおいて,複数センテンスを読みとって,大体同じ長さになるようなシークエンスのbinをいくつか作る
  • shuffling queueもあってデータshufflingに使える

4.7 Containers

  • Varialbeのbacking store

5 Optimizations

工夫の話

5.1 Common Subexpression Elimination

  • computation graphは最終的に同じ計算になることが多いので,同じインプットでオペレーションタイプのコピーは正規化して,一意にしている

5.2 Controlling Data Communication and Memory Usage

  • Receive nodeのスタートは気をつけていて,コントロールエッジを挟んでおき,その前のノードの計算が終わるまでスタートを待っている

5.3 Asynchronous Kernels

  • non-blocking kernelもある
  • 例えば,Receive, Enqueu, Dequeue

5.4 Optimized Libraries for Kernel Imple- mentations

  • 今提供しているkernelはほとんど既存の最適化されたライブラリのthinラッパー
  • BLAS, cuBLAS, cuda-convnet, cuDNNとか
  • Eigenをndarrayを取り扱えるように拡張している

5.5 Lossy Compression

  • ノード間でデータ転送をするとき,32bit to 16bitのlossyな変換をしている
  • IEEE 16bitでなくて,32-bitIEEE 794を使っている

6 Status and Experience

DistBeliefからTensorFlowにportingしたときのレッスン
特にまとめない

7 Common Programming Idioms

Large-Scale Distributed Systemの話で出てくる一般的な用語とその説明

  • Data Parallel SDG synchronouslyできる
  • Data Parallel SDG asynchronouslyできる
  • Model Parallelできる
  • Concurrent Steps for Model Computation Pipeline (Data Parallel SDG asynchronouslyが同じdevicesで行われる)できる

8 Performance

まだないよ

9 Tools

9.1 TensorBoard: Visualization of graph structures and summary statistics

  • いい感じに可視化してくれる
  • 構築したcomputational graphをdrill downでみれる
  • レイヤーにおけるパラメータ,グラディエントの変化履歴をみれる

9.2 Performance Tracing

  • EEGっていうbottleneck発見可視化ツールがあるがまだpublishしてない

10 FutureWork

  • subgraphを完全に取り出せる
  • jit compiler
  • computation 2 device mapping algoの改善
  • node scheduling algoの改善

11 RelatedWork

  • chainer, theanoのようにsymbolic differenciation
  • stateful parameter serverはnodeとして超簡単に表現可能
  • Naiadのように,1つの最適化されたdataflow graphがすべての計算を表し,そのグラフに関するキャッシュ情報は各デバイス上にのせて,コミュニケーションオーバーヘッドを最小化.なので,RAMがたくさん欲しい.

12 Conclusions

OSSにしたから是非使ってくれ.

TensorFlow: Getting Started

Basic Usage

Install
  • cuda 7.0 (gpu使いたい場合)
$ wget "http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_7.0-28_amd64.deb"
$ sudo dpkg -i cuda-repo-ubuntu1404_7.0-28_amd64.deb
$ sudo apt-get update
$ sudo apt-get install cuda
$ sudo apt-get install 

7.0でないと怒られた.というか今はcuda=7.0, cudnn=6.5 v2のみをサポートしているよう.

  • tensorflow 6.0
$ sudo pip install "six==1.9.0"
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.6.0-cp27-none-linux_x86_64.whl # versionは適宜変更
実際に使うまでの2 phases
  • construction phase
    • that assembles a graph
  • execution phase
    • uses a session to execute ops in the graph
Session
  • Computational graphが実行される場所のようなもの
  • graph上のオペレーション(演算)をデバイス(cpu, gpu)にマップする
Varialbe
  • Stateを持つように扱える
  • 詳細は,コード参照
  • 普通はこっち (chainer varialbe にみえる)
  • よく使うのは
    • variable.eval(): 評価
    • variable.value(): Tensor object
    • variable.op: Operation
Fetches
  • Fetchesはsess.run([fetche, ..])といれる.
  • input: list of varialbe, then output: list of nparray
  • input: variable, then output: np.type
Feeds
  • sessの中でデータを関数に食わせるという意味でfeedだとおもう.
  • tf.placeholder(...)を使う
  • こっちはtheano function like

サンプルコードはここ

Graphの作り方は,Theanoに似ているかな.

Interactive Usage

ipythonで使う場合

  • 1. interactive session
  • 2. variable作る
  • 3. variable.initializer.run()
  • 4. varialbe.eval()

こんな感じで評価する(結構めんどい)
こうすることで,sessionの中で保持するvarialbeを保持する必要がなくなる

sess = tf.InteractiveSession()
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35), name="weights")
weights.initializer.run()
weights.eval()

を使う,

Hello TensorFlow

TensorFlow

Googleが出したFlow Graph or Computational Graph 上で数値計算を行えるOSS.
本命どこがOSSでだしてきた.界隈ではゲームのルールが変わるかも.

何ができるか

  • 一般的なDeep Learning
    • Multi Layer Perceptron
    • Convolutional Neural Networks
    • Vector Representations of Words
    • Recurrent Neural Networks (LSTM)
    • Sequence-to-Sequence Models
  • シンボル計算,微分
  • 分散学習 (over nodes も可能な様)
  • 偏微分法的式
  • 可視化
    • 学習履歴,結果
    • 計算グラフのグラフ化

何が嬉しいか

他ライブラリと比較するという観点で4点.

1. Computational Graphおよびエッジ,ノード,学習履歴等,詳細の可視化が可能

現時点では,

  • 学習したモデルをディスクに吐いて
  • 吐いた先のディレクトリを指定したWeb Serverを立ち上げる
  • エッジ,ノード,学習履歴等,詳細がブラウザから見れる

そのうち,ブラウザから学習まで実行するとかでてきそう.

2. Distributed Learning

ここの例を見る感じだとタスクを指定するときに,URIを指定しているので,分散学習が可能.

今のところ,明確なTutorialがないように思えるが, NIPS2015 TutorialにてLarge-Scale Distributed Systems for Training Neural NetworksのTutorialがあるので,その辺で,Visual Object Recognitionがcomming soonでなくなってImagenetをGoogleNetで学習させる例が来るのだろう.

3. SparseTensor

SparseTensorがあるよう.すなわち,0-paddingして,DenseTensorを使わなくてよいということ.

4. Google OSS

Googleが出したということ.すなわち,みんな使う.情報,使い方のHow-toがどんどん増えていく.みんなハッピー.

私の独断と偏見に基づいているので注意.

PythonにおけるShared Memory

前提

pythonはGILの影響でmulti thread programmingでcpu-bound jobが早くならない.
なので,multiprocessingを使うしかない.

CPythonのmultiprocessingはforkなので,unixならcopy-on-write.なので,globで定義したデータなら,Read-onlyに限り,特段気にしないで共有メモリでタスクがパラレルに使えるはずというのは勘違いのよう.この場合は,ref-countが変わって結局コピーが起こるそう.

結局のところ(multiprocessing documentにあるように), shared memory (Value, Array, RawArray)を使って,データを受け渡すしかないよう.Queue/Pipe経由ではなく,os.forkの前に受け渡す.Arrayはdefaultでlockがあるので,lockを気にしないならRawArrayを使う.

実験環境

  • CPU: Intel(R) Xeon(R) CPU X5680 @ 3.33GHz
  • Mem: 52 GB
  • Disk: ST3500418AS
  • OS: ubuntu14.04

Read-onlyなタスク

タスクは,pairwise-similarity (pairwise-innerproduct)を使い,愚直にnumpyで2 loopsを回す.(10000, 100)の行列で,2回10000のloopでdot productをとる.

ここは,numbaを使う,こんなことやらずに,numpyで計算方法の工夫をするなどが考えられるが,それは,out-of-scope.numbaは,python: 行列演算の高速化を参考にされたい.

行いたい比較検証は下記のとおり

1. 1processでnumpyの計算を行う
2. sharedctypes.RawArray + np.ctypeslibで,2と同じことを行う
3. sharedmemを使う

これらで計算速度を比較する

それぞれの検証結果のコードはここ

各実験を10回実行した時の平均,パラでやっている場合は,最大値をとってからの平均.

結果

Exp. index Elapsed time (sec)
1 123.8867863655
2 32.0695706606
3 129.2636404037

Writeありなタスク

タスクは,Read-onlyなタスクと同じで,pairwise-similarity (pairwise-innerproduct)だが,結果を共有メモリに書き出す.

行いたい比較検証は下記の通り

1. sharedctypes.Array + np.ctypeslibで書き込まれるobjectを作る
2. sharedctypes.RawArray + np.ctypeslibで書き込まれるobjectを作る
3. sharedmemで書き込まれるobjectを作る

元のデータは,Read-onlyなタスクでRawArray > sharememだったので,RawArrayで共有する.

これらで計算速度を比較する

それぞれの検証結果のコードはここ

各実験を10回実行した時の平均,パラでやっている場合は,最大値をとってからの平均.

結果

Exp. index Elapsed time (sec)
1 37.442804575
2 37.6960495472
3 38.0742048979

まとめ

ReadもWriteも予想どおりスピードは,#concurrency倍になったが,sharedmemをreadソースとして使った時になぜか,baseの実験(read1)と同じ実行時間になってしまった..., 中身が,mmap.mmapなのが原因なのか...? 

それにしては,baseの実験(read1)と同じくらいの実行時間になってしまったことが気がかり...

Chainerをさわってみた

自分用のまとめなのでDNN知っていたり,Keras, Caffe, Torchとか他のDNN Libraryを知っている人は,公式Docmentを読んだほうがいい.

Github Star数的にはCaffe > Keras >= Torch > Chainer (ただし,chainerを見ているのは日本人くらいだろうから,結構多いとおもう)だが,今からからまともに触るならChainerがアーキ的にイケているという話を効いたのでやってみた.というか,Define-by-Runのおかげで,RNNが簡単に書けるのがイケている.

この記事を書いていた時点ではv1.3だったが,すでにv1.4になっている.

概要

PFN/PFIが作っているDeep Learning Frameworkでpythonで使う.

大まかな特徴は2つだと思う

GPU Array backendはPyCUDA/CuPy

  • 他のtheano-based DNN libraryはCudaNdarray
  • ただし,PyCUDAのフィーチャーがlow-levelすぎるとのことで,彼らはCuPyで置き換えようとしている.PyCUDA numpy interfaceのsubset. v1.3.0から置き換わっているよう.

Define-by-Run

多くのdeep learning libraryはDefine-and-Runでありnetwork (computational graphと言った方がいいかも)を一度defineしたらfixedなので,動的にnetwork構造を変更できないが,Chainerはできる.Define-by-Runは実際のforward-computationのときにon-the-flyでnetwork構造を定義する.そのため,柔軟なことが売りなのだと思う.多分,on-the-flyでnetwork構造を書けるようにすると,RNNの実装が簡単なんだと思う.

比較をみるともう少し詳細な違いがわかる.この表を見ると,大きなdisadvantageとしては,FFT-based Convolutionがないくらい.Stateful RNNs (LSTMのことか?)もあるかもしれないが,Kerasにもあるはず.

特徴ではないかもしれないが,low-level interfaceを公開してくれていて,使う側が柔軟な対応がでいるようになっていると思う.Define-by-Runの範疇かな.

Installation

$ sudo pip install chainer              

基本

Variable

  • 基本的な演算子
  • 微分はbackwordで,y=x^2 + x + 1の微分だとy.backwordでx.gradに結果がある
  • 中間の微分値はdefaultで捨てなので,保持しておきたい場合は,retain_grad=True.
  • 多次元の入力を持つVarialbeでgradientを取るときは,そのVaribleのgradientを初めにセットしておく.error backpropに必要なのだと思う.

Parameterized functions

  • fucntions moduleにあるconnection.pyとか.
  • Affine, ConvolutionとかLayerのことだと思う

FunctionSet

  • DNNにおけるレイヤーセットのような感じ.モデルということ.
  • parameterized functionを入れる.activation functionは入れない
  • FunctionSet.parameters and FunctionSet.gradientsですべてのレイヤーに対するoperationが可能

Optimizer

  • sgd, momentum, adagrad, adadelta, adam, rmspropとかが入っている
  • 基本的な使い方はmnist sampleを見たほうがいい
  • .dot形式のgraphも書く機能があるよう

ここまでの例
ここ

Mnist Sample

ここ

注意点

Towards Chainer v1.5のp.6-9, 19によると, v1.5からLow-level Interface (FunctionSet/Optimizer)が変わるかもしれないので,v1.5からまともに触りだしてもいいかも.

進行が大分早く,半年後にはここに書いた内容がほぼ意味を成さなくなってくる可能性があるので注意.