playground.tensorflow.orgの仕組み

WebUIで機械学習を学習できるplaygroundというツールが、公開されている。このツールを使ったチュートリアルも散見される。
ここでは、該当ソフトウェア構成を見てみた。ソースコードは、GitHub - tensorflow/playground: Play with neural networks!にある。
動作としては、以下の通りである。

  • dist以下のディレクトリに、html/css/jsファイル等を配置する。
  • npmにより起動されたhttpサーバが、dist以下のファイルを提供する。
  • 提供されたhtml/css/js等のファイルは、ブラウザ側で動く。(サーバ側の負荷はなし)

なお、ニューラルネットワークの計算は、src/nn.tsで行っている。

その他の関連ファイル

  1. npm(Javascript用パッケージ管理ツール)
    1. package.json (npmの設定ファイル。依存ファイル名等記載)
      1. npm-package.json | npm Documentation
  2. TypeScript(Microsoftが作ったJavascriptメタ言語)
    1. Documentation · TypeScript
    2. tsconfig.json (TypeScriptの設定ファイル)
      1. http://www.typescriptlang.org/docs/handbook/tsconfig-json.html
    3. tslint.json (TypeScriptのチェックツール)
      1. TSLint
    4. typings.json (TypeScriptの型定義ツール)
      1. GitHub - typings/typings: *DEPRECATED* The TypeScript Definition Manager

PythonのGlobal Interpreter Lock (GIL) について

Python (CPython) では、インタープリターはひとつしかない。このため、複数のスレッドを走らせた場合、ある時点ではひとつのスレッドしか動かない。このためのスレッド同期機構を、Global Interpreter Lock (GIL) という。PythonでのGIL自体は、1992年の初期実装から変更が無い。しかし、Lockのスレッド間引渡し方法が、Python 3.2から変更されている。これにより、CPUインテンシブプロセスでの複数コアで複数スレッドを動かした場合の性能劣化を改善している。
ここでは、2.7と3.5を比較してどのように違うかを説明する。Python 2.7は、interpreter_lock (GIL) と _Py_Ticker (GIL監視間隔 大まかに命令数100が標準)からなる。なお、切り替え間隔は、sys.setcheckintervalで設定することが出来る。この方式では、スレッド間でロックを取り合って実行を継続する。別コアで動いているスレッド間の場合、ロックの開放情報をシグナルで別コアに送るのは時間がかかる。このため、CPUインテンシブプロセス間のコンテキストスイッチは、ほぼ永遠に発生しない。このため、全体として処理効率が落ちる。
Python 3.5は、gil_locked (GIL) 、gil_drop_request (GIL要求)および gil_interval (GIL監視間隔 5000マイクロ秒 (5ミリ秒) が標準) からなる。なお、切り替え間隔は、sys.setswitchintervalで設定することが出来る。この場合、gil_drop_requestをスレッド間のフラグとして用いる。待ちスレッドがフラグを設定して要求し、一定時間後実行スレッドが、フラグを確認しスレッドのロックを開放し、待ちスレッドに実行件を譲る。これにより、マルチコアでも、効率的にコンテキストスイッチを行うことが出来る。
とはいえ、Python3.2以降に簡単に切り替えられない(たとえば、Python 2.xベースであり、Python 3.xへ移行できない)という場合もありうる。この場合、Pythonプロセスの実行するコアを指定する等の対策が必要と考えられる。言うまでも無く、CPUインテンシブプロセスが6つあれば、6つのコアにそれぞれ指定する等が考えられる。

マニュアル

ソースコード

その他の参考資料

 Pythonのバイトコードまで

PythonスクリプトからPythonバイトコードまで、どうなっているかを追いかけてみた。
具体的には、Pythonスクリプトから、pycファイルが保存されるまでである。
コマンドラインスクリプトで実行する場合は以下に相当する

# python -m compileall file.py

import py_compile
py_compile.compile("file.py")

Pythonスクリプトは、パースされ、AST (抽象構文木) を生成し、CFG (制御フローグラフ) となり、バイトコードとして生成される。CFGから、バイトコードは、assemble()で生成する。
pycの書式は、以下からなっている。(_code_to_bytecode()関数にて)

  1. MAGIC_NUMBER
  2. mtime
  3. size
  4. code

ついでながら、codeは、marshall(シリアライズ)している。

Heat/Autoscaling

HeatのAutoScalingは、Ceilometer (Newtonからは、Aodh)のサーバ等の負荷の信号を用いて、スケールさせる。
フローとしては、以下の通り

  1. Heat EngineからCeilometerにシグナルを登録
  2. Ceilometerから、Heat_API_CFNに変更を通知
  3. Heat_API_CFNから、Heat Engineに変更を通知 (handle_signalが稼動する)
  4. Heat Engineは、スケールインもしくはアウトする (サーバの起動又は停止)

なお、スケールの変更可否は、Cooldownクラスで行う。


参考資料

コマンド

ソースコード

Python2*3(six)での違い(printの改行)

Pythonの版数が、2から3になったことに伴いprint文の位置づけが、ステートメントから関数に変わっている。このためか改行の方法も、変わっている。
版数違いの互換性を確保するためには、sixを使って動くように直す必要がある。

OpenStackでのoslo_service/eventlet/greenlet

OpenStackの各コンポでWSGI (Web Service Gateway Interface) をどう実現しているか?の観点で見ると、eventlet.wsgiを使っている場合が多い。
そして、eventlet.wsgiを効率的に動かすために、Greenletを使っている。なお、Greenletは、C言語拡張モジュールによるPython用のGreenThread実装である。このため、Pythonで実装したよりも、スレッド間切り替えが早い。
また、oslo_serviceを介してeventletを間接的に呼び出しているコンポもある。
2016年8月20日時点 (Newtonリリースの前) のコードでは、eventletのWSGIフレームワークの使用状況は以下の通りである。

コンポ名 eventlet使用している? oslo_serviceから使用している?
cinder
glance ×
heat ×
ironic
keystone × ×
neutron
nova ×

参考資料

OpenStackでのPythonコーディング規約チェック

OpenStackの場合hackingモジュールでPythonコード規約をチェックする。ただし、個別のコード規約は、モジュール毎のHACKING.rstに記載されている。そして、実際の個別チェックツールもhackingディレクトリにスクリプトがおかれている。出力されるエラーコードは、PEP8ベースのE/W系およびhackingベースのH系に分かれる。そのほかに、各コンポごとに設定されたエラーコードが出力される。ふと見るとNは、Nova/Neutronでコード番号がかぶっている。