singularityの使い方
はじめに
singularity v3.6.0時点での記事です
メリット
- SingularityとはDockerと同じコンテナプラットフォームで,主にHPC向けに作られたオープンソースソフトウェア
- Dockerより簡単にGPUを使うことができるらしい (最近はnvidia-dockerがdockerに統合されたため,このメリットは微妙)
- Docker互換(Dockerfile, Docker imageを持ってくることができる)
- rootlessでも動作
- 自動で以下の領域をマウント(sudo付けないと一部マウントされないかも)
host | singulalrity |
---|---|
$HOME | $HOME |
/sys | /sys |
/proc | /proc |
/tmp | /tmp |
/var/tmp | /var/tmp |
/etc/resolv.conf | /etc/resolv.conf |
/etc/passwd | /etc/passwd |
$PWD | $PWD |
Dockerとの違い
SingularityのアーキテクチャはDockerと少し異なります. Singularityのコンテナは
- immutableな*.sif(Singularity Image File)
- muutableなsandbox (フォルダ)
の2種類あります. Dockerのコンテナは変更可能なので,singularityで言うsandboxに該当します.
$HOME
などが自動マウントされるので,基本的はsifを使うみたいですが,sifを使ったコンテナは後々pipでライブラリを追加したり出来ません.
Dockerコンテナライクな使い方をしたい場合や,環境を作って行きたい場合はsandboxを使うことをオススメします.
sandboxである程度環境が整った後に.sifに変換することも可能です. - sandboxで扱った後にimuutableにする方法
singularity build some-image.sif sandbox-dir
コンテナ作成方法
- Docker Hub,Singularity Hub, Container Libraryからビルド
- マシン上の既存コンテナからビルド(Docker Imageも可)
- Singularity定義ファイル*.defからビルド
の3種類の方法があります.
build
コマンドを使用してコンテナを作成します.
Usage: singularity build [local options...] <IMAGE PATH> <BUILD SPEC>
コンテナ作成例
pytorch/conda-cudaをDocker Hubから.sif作成
- conda-cuda-torch.sifという名前の.sifファイルを作成する例
singularity build conda-cuda-torch.sif docker://nablascom/cuda-pytorch:latest
sandboxでコンテナを作成するオプション
--sandbox
オプションをつけてIMAGE PATH を任意のフォルダ名(ここではconda-cuda-torch)にすればOK
singularity build --sandbox conda-cuda-torch docker://nablascom/cuda-pytorch:latest
マシン上のdockerにあるhello-world imageから
singularity build hello-world-singularity.sif docker-daemon://hello-world:latest
conda-torch.defから
- Dockerfileに相当するSingularity Definition File(.def)からビルドする例
- sudoが必要
sudo singularity build conda-torch.sif conda-torch.def
コンテナ実行方法
実行コマンドは以下の3つあります.
この記事から引用すると
cmd | 説明 | Usage |
---|---|---|
exec |
ホストシステム上で直接実行されているかのように、 コンテナイメージ内の任意のコマンドを実行できます。 |
singularity exec [exec options...] <container> <command> |
shell |
コンテナ内に対話型シェルを自動的に生成します。 | singularity shell [shell options...] <container> |
run |
コンテナがファイル名で直接実行または実行されたときに 実行されるカスタムアクションを定義できます。 |
singularity run [run options...] <container> |
また,先程作成したコンテナを元にいくつか実行例を示します.
- cuda torch検証用スクリプト
import torch dev = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print(dev)
conda-cuda-torch.sifの環境上でpythonスクリプトを実行
- sandboxの場合は.sifの部分に対応するフォルダ名を指定すれば良い
singularity exec conda-cuda-torch.sif python check_torch_cuda.py $ cpu
GPU環境でpythonスクリプト実行
--nv
オプションをつける
singularity exec --nv conda-cuda-torch.sif python check_torch_cuda.py $ cuda:0
shellに入る
singularity shell --nv conda-cuda-torch.sif $ Singularity>
sandbox環境に書き込み可能な状態でshell実行(Dockerのコンテナはこの状態)
- デフォルトは読み取り専用なので、
--writable
を付ける
singularity shell --nv --writable conda-cuda-torch $ Singularity>
run補足
- sif作成時,
%runscript
を指定することで,singularity run file_name.sif
もしくは./file_name.sif
のように実行形式ファイル風に実行できる
port forwardingについて
jupyterを使いたい場合があると思いますが,Singularityはデフォルトで多くの領域をマウントするので,勝手にhostのポートを使ってくれます.(webカメラ等も同様)
DBやWebサーバ等をバックグラウンドで実行したい時
Dockerライクなインターフェイスとして,singularity instance
コマンドがあります.
詳しくはこちらのDocumentへ - https://sylabs.io/guides/3.6/user-guide/cli/singularity_instance.html
singularity instanceでバックグラウンド実行する方法
- 一応jupyter notebookをバックグラウンドで実行して停止する例を一つ出しておきます.
- もちろんDockerのようなポートフォワーディングの記述は不要です.
# cuda-torchは INSTANCE NAME singularity instance start --nv conda-cuda-torch.sif cuda-torch # docker ps的なコマンド singularity instance list $ INSTANCE NAME PID IP IMAGE $ cuda-torch 14030 /home/oda/conda-cuda-torch.sif # shell起動 singularity shell instance://cuda-torch Singularity> jupyter notebook ... # exitで抜ける Singularity> exit # インスタンスを停止 singularity instance stop cuda-torch # インスタンスがないことを確認 singularity instance list $ INSTANCE NAME PID IP IMAGE
まとめ
- Docker互換
- コンテナはimmutableな.sifとsandboxがある
- build時に
--sandbox
を指定しかつ,実行時に--writable
を指定すると書き込み可能 - 実行は
exec
,shell
,run
がある - 実行時,勝手にマウント
--nv
コマンドだけでGPU対応- バックグラウンドで動かしたいときDockerライクなコマンド
instance
がある
参考
公式Document top page
公式Document Quick Start
公式Document Build
- 公式Document Instance
https://sylabs.io/guides/3.6/user-guide/cli/singularity_instance.html
- SingularityでDockerコンテナを使いたい
- [第2回 Singularity 勉強会] Singularity Hands-on
- SingularityコンテナをBuildする方法まとめ(Singularity v3.0.3)
PFN2020インターンの課題 解答
PFN2020インターンに応募した話
M1になり,そろそろ夏インターンを探さなきゃってことで,色々応募しました.
強化学習のインターンをやりたかったのですが,勉強不足を面接であっさり見抜かれてしまい,落ちてしまいました.
これを糧に,これから強化学習の勉強をしっかりしようと強く思いました.
現在はberkeleyの強化学習スライドをベースに,基礎的な部分の勉強をしています.いずれはそれをまとめた記事を公開しようと思ってます.
PFN2020課題
Github上で2020の課題が公開されたので大丈夫だとは思いますが,もし何か差し支えるようでしたら,ご連絡頂けますと幸いです.
こちらのリポジトリに解答例を載せましたので,ソースはこちらをご覧ください. github.com
また,問題文はこちらです github.com
PFNの課題というと,深層学習のイメージがありましたが,今回はかなり競プロっぽい内容でした. 最近はそういう流れなんですかね.
また,大問が3つあって,それぞれコーディング課題と,その正しさを検証する課題の2つセットで解答する必要があります.
もし数式が正しく表示されていなければ,ブラウザをリロードしてみてください.
Q1
3つの整数 x, y, d が与えられる。 3x3 行列の各要素を x または y で埋めるとき、行列式がちょうど d になるような 埋め方は何通りあるか数えよ。
問題の解法説明
まず最初に思いつくアプローチは全探索である.
しかし,3x3行列というのは各列を3次元ベクトルと見ると,平行六面体を表しており,行列式の値はその体積に相当する.つまり同じ向きのベクトルが存在すると体積は0になる.この性質を利用して計算量を減らした.
$d \neq 0$ の場合
- 3次元ベクトルそれぞれが取ることができるx, yの組み合わせは$2^{3}=8$通り
- そこから重複なく3つ選ぶ数は ${}_8 C_3 = 56$ 通り
- また,ベクトルをそれぞれ入れ替えて行列式の符号が同じになるような組み合わせは3通り
つまり56通り検索し,見つかった数×3すれば良い.
$d == 0$の場合
- 同じく56通り調べる(転置してベクトルが0になる場合)
- 重複する選び方の数(=全通り - 重複しない数)を計算
行列式が0なので,見つかった数×6に重複する選び方の数を足せば良い.
プログラムの正しさの検証
q1_in.txt
を総当りのプログラムとの出力の比較を行った.
境界条件としてdが正・負・0, x, yが同符号・異符号・0の場合のすべての組み合わせ(12通り)について検証を行った.
また,おまけとして,全通りでも制約すべての条件下で現実的な時間内に終わりそうだったため,q1_validation_extra.py
にてすべての場合の検証を行った.
進捗を見やすくするため,tqdm
という外部ライブラリを使用した.(並列化してますが,それでも手元の6コアCPUで30分程度かかりました)
Q2
文字列 S1, S2, ... を以下で定める。
- S1 = "a"
- S2 = "b"
- S3 = "c"
Sk = Sk-3 + Sk-2 + Sk-1 (k ≥ 4) (ここで、+ は文字列の結合を表す) 例えば、S4 = "abc", S5 = "bcabc" である。 3つの整数 k, p, q が与えられる。 Sk の p 文字目から q 文字目までに含まれる文字 "a", "b", "c" の個数をそれぞれ求 めよ。
問題の解法説明
まず最初に思いつくアプローチとしてDPがある.しかし試してみたところ,メモリが$k > 40$をこえたあたりで足りなくなった.
そこで,この漸化式の行列表現を考える.
とすると以下のように表現できる.
このとき,$a_k$とは,文字列$S_k$に含まれるaの個数である.
このAを毎回累乗して求めても良いが,高速化のためにこのAを対角化してn乗を求めておく. すると$O(1)$で,文字列$S_k$に含まれるa, b, c の個数がわかる.
また,この行列は固有値に虚数を含むため誤差が生じる.しかし,$A^{50}$のときの誤差が $ [0.0144 +0.0016j, 0.0124+0.0014j, 0.0072+0.0013j] $ であるため,問題ないと言える.
(当時は2乗法を知らずn次行列を求めてますが,あまり美しい方法じゃないので,2乗法を使ったほうが良いと思います‥)
つぎに$[p, q]$だが,もし,$[p, q]$の範囲が,ある の文字数と同じ場合,先程の行列の結果をそのまま返せば良い. つまり,そのような$S_l$を探せば良い.
$S_k$は の3つの文字列から構成されている. つまり,$[p, q]$は$S_k$の各構成要素を跨ぐ場合と,そうでない場合に分けることができる.
以上の性質を用いると以下のようなアルゴリズムを考えることができる.
区間が跨いでいる場合
- それぞれを区間を跨がないように分割し,最後にそれぞれの結果を足す
区間が跨いでいない場合
- $[p, q] = S_{l}$ ならば,行列計算の結果を返す
- $[p, q] \neq S_l$ ならば,対応する部分の$S_m, (m < l)$を調べる
以上の手順を再帰的に繰り返すことによって調べることができる.
プログラムの正しさの検証
プログラムの境界条件と,それぞれが1回以上の文字連結で構成されている$k=7$でのすべてのケースについて検証を行った.
また,DPで解くプログラムの限界が$k<40$であるので,その条件に満たすq2_in.txt
でも同様に出力の検証を行った.
Q3
長いので省略
問題の解法説明
まず考えられるアプローチとして,各距離をすべて保持する方法が考えられる.
単純に,ある$j$番目人を最も距離が大きいかつ一番左の$a_j$に座らせて,$a_j$から両端まで距離を更新して行けば良い.
しかし,この手法は$O(n^{2})$であり,制約の$n$が大きいため時間がかかる.そのため高速化を考える.
ある$j$番目の人が$a_j$に座ったとき,そこから$l$方向($0 < l < j$)と, $r$方向の区間($j < r \leq n$)のまだ誰も座っていない区間に分割する.
それぞれ分割された区間の中で,区間の左右から最も離れた位置が最も大きい場所に座れば良い.
つまり,分割された区間が$l$から$r$とすると($l$は0から),その区間内で離れることができる最大の距離$dist$は$(l - r) // 2$であり,
座る位置のindexは$l + dist$として表現できる.また,$dist$が最も大きいものから(同じからlが小さい方)から選んでいけば良い.
この手順を再帰的に繰り返し適用していけば,すべての座る位置が求まる.
しかし,最初の分割だけ例外があり,端に誰も座っていないため2で割る必要がない.よって$dist = l - r$とした.
実装上の工夫として,$dist$の最も大きい値を効率的に探すためにheapqを用いた.
プログラムの正しさの検証
プログラムの境界条件(最初に端に座る,n=1など)の検証を行った.
また,$O(n^{2})$の方法が現実的な時間で終わるのが$k < 10000$なので,その条件を満たすq3_in.txt
についても同様の検証を行った.
Top-K Off-Policy Correction for a REINFORCE Recommender System
スライド
説明
Top-K Off-Policy Correction for a REINFORCE Recommender System – Google Research
YouTubeで実際に運用された(今も運用されてるかは不明)強化学習を用いた推薦システムの論文です.
内容として,RENFORCEをoff-policyかつ複数の行動を出力するように変更したみたいです.しかし,この推薦システムが性能良いのか悪いのかについて議論されていないので,そこが気になりますね.
でも,この数百万オーダの空間へスケールアップと,バイアス・バリアンスへの対処は,強化学習の非常によい勉強になりました.
スライド中でも軽く方策勾配法について解説しているので,良かったら見てください.
参考にしたサイト
有志実装
Azure Web App + Flask + Github Actionsで認証ページ付きポートフォリオをデプロイする方法
はじめに
以前Firebaseでデプロイしたときをベースに書いてますので、先にこちらを見て下さい。 tmyoda.hatenablog.com
Azure クラウド サービス | Microsoft Azure にはとんでもない数のサービスがありますが 、 今回はポートフォリオを公開するために、WebのApp Serviceを使用しました。分類的にはPaaSですかね。
そしてなにより、1Gメモリ F1を選択すると無料で使えます。 また、学生でしたら、登録したときに1万円分のサブスククーポンを貰えます。
概要
- AzureでWebページをデプロイ
- AzureではBasic認証が使えないので、ログインページを用意(Flask)
- 以前Firebaseでデプロイしたhtml,css,jsを使いまわしたいのでサブモジュールにて保持
参考にさせて頂いた記事
Azure登録まで
参考記事に従ってAzureを登録します。 このとき、Flaskを使いたいのでランタイムスタックをPython3にします。
しばらくするとインスタンスが作成されます。
Flaskで認証ページを実装
Firebase Hostingでデプロイしたときは、Basic認証が使えたので、実質静的ページの公開と同じでした。
しかし、AzureはBasic認証が使えないようなので、Flaskでかんたんなログインを実装しようと考えました。 参考記事に従いながら実装していると‥
なんと、Flaskでhtmlを表示するにはjinja2のテンプレートに対応した記述が必要です。
しかし、サブモジュールでhtmlを保持しているため、書き換え等はしたくない、、、
かといってFlaskのstaticフォルダに格納したら直接が見られるが認証がかけられない、、、
そこで、
@app.route('/portfolio/')
にGETが来たら、直接htmlをテキストとして読み出しResponse
型で返す- その他のcss,jsへのアクセスが来たら、
send_file
する
といった方針でひとまずやりたいことは実現しました。
解決策
from flask import Flask, request, Response, abort, render_template, redirect, url_for, send_file from flask_login import LoginManager, login_user, logout_user, login_required, UserMixin from collections import defaultdict import os import logging app = Flask(__name__) login_manager = LoginManager() login_manager.init_app(app) app.config['SECRET_KEY'] = なんらかしらのキーを設定 # logging setting logging.basicConfig(level=logging.DEBUG) #logging ex # app.logger.info("Hello World %s", variable) # path setting currnet_dir = os.path.dirname( os.path.abspath(__file__) ) static_dir = 'portfolio/functions/static/' class User(UserMixin): def __init__(self, id, name, password): self.id = id self.name = name self.password = password # ログイン用ユーザー作成 users = { 1: User(1, "user01", "password"), 2: User(2, "user02", "password") } # ユーザーチェックに使用する辞書作成 nested_dict = lambda: defaultdict(nested_dict) user_check = nested_dict() for i in users.values(): user_check[i.name]["password"] = i.password user_check[i.name]["id"] = i.id @login_manager.user_loader def load_user(user_id): return users.get(int(user_id)) # css, js ,imgなどのコンポーネント呼び出し用 @app.route('/portfolio/<path:path>/<string:filename>', methods=["GET"]) @login_required def portfolio_content(path, filename): return send_file(static_dir + path + "/" + filename) # index.html呼び出し # .htmlはこの方法じゃないとだめみたい @app.route('/portfolio/') @login_required def portfolio(): with open(currnet_dir + '/' + static_dir + 'index.html') as f: txt = f.read() return Response(txt) # ログインパス @app.route('/', methods=["GET", "POST"]) def login(): if(request.method == "POST"): # ユーザーチェック if(request.form["username"] in user_check and request.form["password"] == user_check[request.form["username"]]["password"]): # ユーザーが存在した場合はログイン login_user(users.get(user_check[request.form["username"]]["id"])) return redirect(url_for('portfolio')) else: return abort(401) else: return render_template("login.html") # ログアウトパス @app.route('/logout/') @login_required def logout(): logout_user() return Response(''' logout success!<br /> <a href="/login/">login</a> ''') if __name__ == '__main__': app.run(threaded=True)
pass,idベタ書きしてますが、本当はDBに格納してパスワードもハッシュ化しないといけませんね。 まあ最悪全世界に晒されても良い内容なので、今回はこの程度で良いでしょう。
/portfolio に来るアクセスはindex.htmlを返して、 /portfolio/img/, css/ とかはsend_fileで返却します。
フォルダ階層
. ├── Pipfile ├── Pipfile.lock ├── app.py ├── portfolio │ └── functions │ └── static │ ├── css │ ├── img │ ├── index.html │ ├── js │ └── vendor ├── requirements.txt └── templates └── login.html
この工夫点として、portfolioフォルダは別リポジトリのサブモジュールです。 なので、どっちかでポートフォリオをアップデートしたら、もう片方がアップデートされます。
また、 staticフォルダを作成していない点もポイントです。(staticは外から見える)
そして、Pythonは、*.py、requirements.txt、または runtime.txt
が最初に呼び出されるらしいので、
名前をちゃんと変えておきましょう。
デプロイ
ここまできたらいよいよです。今回はGithub Actionsでのデプロイが目標ですので、Azure portalのデプロイメントから、 Githubを選択して、Actionsを選択します。(要認証)
すると勝手にworkflowが作成されるので、次々と進むと勝手にCI/CDが走ってデプロイ完了です。 非常にかんたんですね!
注意点として、再起動しないと認識されないので注意です。
サブモジュール関連のトラブル
サブモジュール使ってない人はパスして下さい。
サブモジュールがpullされておらず、htmlがNot Foundになりました。 その解決方法として、追記したworkflow/ymlを晒します。
steps: - uses: actions/checkout@master with: submodules: true token: ${{ secrets.PORTFOLIO_ACCESS_TOKEN }} - name: Sparse-Checkout run: | echo /functions/static >> .git/modules/portfolio/info/sparse-checkout cd portfolio git config core.sparsecheckout true git read-tree -mu HEAD git checkout master cd ..
まず、プライベートリポジトリでしたので、アクセストークンを取得して設定する必要があります。
以下を参考に作成して、サクッと設定しましょう。見ての通り、token: ${{ secrets.PORTFOLIO_ACCESS_TOKEN }}
で埋め込めます。
また、私の場合はhtmlに関係するファイルのみ欲しかったので、sparse-checkoutしています。 一括でうまくやってくれるworkflowファイルを見つけられなかったので、runでベタ書きしました。
とりあえず、これで上手く動いてくれているので良かったです。 (すぐデプロイするつもりがなんだかんだ一日かかっちゃいました‥)
注意点
- 再起動しないとデプロイが反映されない
- privateリポジトリをサブモジュールで持つなら、Access Tokenが必要
- FlaskはStatic以下は常に晒されている
- Secretkey pass, idなどはちゃんとDB管理
追記
Azureは適当にhtmlファイル置くだけでも表示されるらしいので、なんかのWebサーバが裏で動いているんですかね、わかりません。
そしてなんと、Azure Static Web Appというより気軽なサービスが最近追加されたらしいです‥ こっち使ったほうが早かったですね
Learning agile and dynamic motor skills for legged robots 解説スライド
スライド
説明
- 複雑なモータ制御が必要なロボットの制御方法を提案
- シミュレーションのみで学習した方策をロボットに転送し、実 環境のロボット制御に成功
- ロボットのシミュレーションとの違いをNNによって吸収
- これによりシミュレータでのモデリングが改善
- 方策はシミュレーション上のみで学習
- 既存のSOTAのモデルベース手法より優れた性能
- より、少ないエネルギー、計算量ながら、より高速で高い精度
- 本論文は多脚ロボットの汎用的なコントローラの獲得への一歩
感想
actuator netの精度を向上させたら、ゴリゴリのコスト関数設計はもう少し楽になるのでしょうか‥
恐らくノイズを載せまくってるのがコスト関数を複雑化させている原因になっているので、もう少しシミュレーションが
現実に近いと楽なんですかね
また、TRPOじゃなくてPPOとかSACとかだと学習に違いが出るか気になります
論文のpdfをコピペしたときのいらない改行を削除する
追記 (2020/12/07)
Webで動く便利なサイト見つけました
はじめに
論文を翻訳にかけるとき、単純にCtrl+Cすると余計な改行がはいって非常に煩わしいですよね
そこで、クリップボードを監視して、改行を取り除く簡単なPythonスクリプトを作成しました
導入方法
Githubにて公開しました github.com
こちらをcloneしてpyperclipをインストールすればすぐに使えます
webページとかを介さなくて良いので安心ですね(?)
注意点
- ソース内
pause
パラメータをいじることができますが、あまり短くしすぎると無限ループに陥ります - ほんとはDeepL翻訳のショートカットであるCtrl+C 2回と組み合わせて使えたら最高だなと思ったのですが、難しかったです‥(PRお待ちしております)
- とりあえずで作って見た次第なので、改善案等お待ちしておりますー