Ubuntu on Vagrant の備忘録 (1)

そろそろCentOSでは対応が面倒な場面が増えてきたので、Ubuntuに移行すべく作業中。であるが、不慣れなので思ったように作業が進まない。

app.vagrantup.com

1. パスワード

CentOS on Vagrantだとrootのパスワードはvagrantだが、Ubuntuは違うらしい。以下のコマンドでパスワードを設定できる。

$ sudo passwd root

2. 開発環境

2.1. コンパイラなど

とりあえず以下を実行。

$ sudo apt update
$ sudo apt install build-essential
$ sudo apt install bison flex
$ sudo apt install binutils

追加で以下も。

$ sudo apt install libreadline-dev
$ sudo apt install zlib1g
$ sudo apt install zlib1g-dev
$ sudo apt install libssl-dev

さらに以下も。

$ sudo apt install gdb
2.2. emacs

以下で良さげ。

$ sudo snap install emacs --classic

3. Python関係

最新版のUbuntuを入れたら、Pythonは3.9だった。ラッキー。

しかしUbuntuはpipを独自拡張しているらしい。なんだそりゃ。

$ sudo apt install python3-pip

後々面倒が起きそうで嫌な感じである。

4. ML関係

とりあえず定番のscikit-learnを、numpyやpandasと共に。

$ pip install numpy scipy joblib matplotlib scikit-image pandas
$ pip install -U scikit-learn

ついでTensorflow+Keras.

$ sudo pip3 install tensorflow
$ sudo pip3 install keras

プロファイラの備忘録 (1) gprof

たまにしか使わないのでいつも「perfだっけ?gperfだっけ?」とプロファイラの名前から検索している。 あまりにも効率が悪いのでここに使い方メモを記す。

1. 準備

1.1. gprof

gprofはbinutilsに含まれるらしい。

$ sudo yum install binutils
1.2. PostgreSQL

configureに--enable-profilingオプション(と--enable-debugオプション)を設定して実行。これで-pg ( と-g)オプション付きでgccが実行される。

2. データ収集

特に準備は不要で、PostgreSQLを起動すればよい。 停止したプロセスのgmon.outが data/gprof/"プロセス番号/gmon.out"に書き込まれる。

$ find data/ | grep gmon
data/gprof/2766/gmon.out
data/gprof/avworker/gmon.out
data/gprof/2776/gmon.out
data/gprof/2775/gmon.out
data/gprof/2774/gmon.out
data/gprof/2768/gmon.out
data/gprof/2770/gmon.out

... 略 ...

よって、ある一つのSQLのプロファイルを行いたい場合、(1)SQL毎にpsqlでプロセスを立ち上げ、(2)pg_backend_pid()でプロセス番号を確認して、(4)SQL*1を実行、(3)実行後は即座に終了、する。

$ psql testdb
psql (14beta2)
Type "help" for help.

testdb=# SELECT pg_backend_pid();
 pg_backend_pid 
----------------
           2774
(1 row)

testdb=# SELECT count(*) FROM a1, a2;
 count 
-------
  2000
(1 row)

testdb=# \q

3. データ表示

最も単純に結果を知るには、以下のようにする。

$ gprof ./bin/postgres  data/gprof/2774/gmon.out


Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 12.50      0.67     0.67 166400001     0.00     0.00  ExecNestLoop
 12.12      1.31     0.65 332803335     0.00     0.00  ExecInterpExpr
 12.03      1.95     0.64 166403415     0.00     0.00  heapgettup_pagemode
  6.02      2.27     0.32 166403328     0.00     0.00  SeqNext
  5.83      2.58     0.31 499241656     0.00     0.00  MemoryContextReset
  5.45      2.87     0.29 166403415     0.00     0.00  heap_getnextslot
  4.70      3.12     0.25   739109     0.00     0.00  heapgetpage
  4.51      3.36     0.24 166401650     0.00     0.00  ExecStoreBufferHeapTuple
  4.51      3.60     0.24 166400005     0.00     0.00  fetch_input_tuple

... 略 ...

*1:pg_backend_pid()の実行が無視できる程度の負荷をかける必要がある。もしも軽いSQL処理のプロファイルを行いたい場合はpsコマンドで直接プロセス番号を確認したほうがよい。

スカンクワークとワクチン

昨年末からコツコツと仕事の合間に作っていたプロダクトを今朝、リリースした。

github.com

思いの外時間がかかって結局7ヶ月強費やしたが無事リリースできた。(一応アリバイ作りのような感じで仕事の方は昨日会社のリポジトリにPushしておいた。)

で、ワクチンである。

なんだかんだ言って血栓など万が一のリスクもあることは承知の上で*1、それでも打たないことには日本含めてどこにも移動できないため、上のプログラムができた段階でワクチンを打つことにしていた。 で、今予約をして明日7月30日と来月8月27日にワクチンを打つことになった。 明日以降反応が無くなっていたら、ワクチンの影響ということで。

f:id:interdb:20210729184313p:plain
予約完了画面の一部

世界の製薬会社TOP3のうち2社があるスイスのくせに、ヨーロッパの中ではワクチン供給が遅れていた。しかし、それでも5月頃には普通にワクチンが打てるようになっていた。承認されているのはファイザーとモデルナ。アストラゼネカは承認されていない*2

システムは完全にネットでの予約制で、まずはサイトに登録し、希望日の状況をみて予約を入れるシステム。 登録できるのは健康保険に入っている人間で、ということは住民登録している人間は原則的に登録可能。 逆に言えば、他のヨーロッパ諸国と比較すると非常に少ないがそれでもごく少数いるホームレスは打てない。これはなあ、と思う。この辺りはスイスは冷たい。

アイルランドでもそうだったが、公共機関のどのようなサイトであれ、インターフェイスの設計がどの国もどの組織も同じような作りになっていて、入り口のサイトにさえ辿りつければほとんど迷うことはない。こういう、ユーザとのインタフェースが整然としている”システム”をみると、内部のモジュール間も整然と設計されているだろうなと思うし、そもそも”システム”というものを皆が理解して作り、メンテし、使っているのだろうなあと感じる。

閑話休題

2回分の予約を同時に入れなければならないが、2回目の日付は4週間後に固定で選べるのは時刻だけ。当たり前か。

今月中旬にドイツやベルギーで大洪水が起きたように、この夏はヨーロッパ全土で豪雨、雷雨が多く、スイスも例外でない。 明日ワクチン注射を決めたのは、直近の1週間で予報が曇りなのは明日の午前中だけだったからだが、8月27日がどうなっているかは不明なのでちょっと怖い(非常に雷雨が多い)。

*1:家系的にその手の疾患が多いし、その手の数値が子供の頃からちょっと悪い。 先月話題になったこの件、欧州の航空会社は血栓の恐れからワクチン摂取者の搭乗を見合わせるよう勧めていることからも、公に懸念されるほどのリスクがある。

*2:日本でもアストラゼネカは承認したが公的には使ってない。 https://answers.ten-navi.com/pharmanews/20139/  なぜワクチンと名がつけば無条件にOKな人が多いのは何故だろう? どんなものであれ良いものも悪いものもあるから、個別に判断しなけりゃならないと思うのだけども。「ワクチン、調べたけど原理的に問題ないっしょ」なんて、治験結果も論文も読み込まずにそこらのまとめサイトの情報だけで言い切るなど、命に関わる部分についてなぜそれほど雑な理解で安心できるのか、いつも不思議に思っている。

pg_plan_inspector

機械学習*1の手法を使ってPostgreSQLのモニタリングとパフォーマンス向上を目指す目的で開発していた pg_plan_inspectorというフレームワークを公開した。

とりあえず動画を。

この動画は、クエリの進捗を推測して表示するモジュールのデモ動画である。

f:id:interdb:20210729122705p:plain
アーキテクチャ

詳細はREADMEを参照。

開発動機

このフレームワークの開発動機は以下の2つ:

  1. (純粋な外部モジュールだけで、つまりPostgreSQL本体を改造することなく)リアルタイムでクエリの実行状況をモニタリングする。
  2. 常に捨てられているクエリの実行計画を使って、クエリプランの改善を行う。

現在のステータス

このフレームワークはまだ開発が始まったばかりで、POC(Proof Of Concept)モデルである。

現時点で開発動機の1.については達成できた。

開発動機の2.については、簡単なツールでテーブルの属性間の関数依存性を抽出し、拡張統計(Extended Statistics)を設定すべき候補をリストアップすることができることを示した。詳細はREADME-tools参照。

今後について

今後について、現時点では2段階の開発プランを持っている。

Step 1

現時点でクエリの進捗を推測するために、線形回帰モデルでOptimizerの推定したPlan Rowsを補正している。 逆の見方をすれば、Optimizerが推定する際に補正してもよいはずである。

実際、同様のアイディアは(アプローチや実装方法は異なるが)pg_plan_advsrが既に実現している。

よってStep 1では、回帰モデルで得たパラメータをPostgreSQL側に渡し、Optimizerの推定値を補正する機能を実現する。

それから、今はアドホックな手法で関数依存性を抽出しているが、そのアルゴリズムも改良する予定。

Step 2

これまでの実装の過程で、線形回帰モデルによる補正はNested Loopには比較的有効であることがわかったが、 Hash JoinやMerge Joinでは補正が難しい場合が多いこともわかっている。 また、テーブルの属性間に関数依存性があるとPostgreSQLのoptimizerは不正確なPlan Rowsを推定してしまい、線形回帰モデルでは補正できない状況になることも多い。

これらの問題に、近年ではAI(もしくは広く機械学習)の手法を使ってアプローチする論文やプロトタイプが数多く発表されている。 詳細はリファレンスの[6]や[7]などを参照のこと。

リファレンスに示したシステムのうち、いくつかはgithubソースコードが公開されているので、使えるものは取り込んでしまおうと思っている。

またこれらは研究が目的であるため、純粋に正確なCardinality Estimationを得るアルゴリズムの開発を主眼としているようだが、 こちらは開発者なのでうまく動けばどのアルゴリズムでもよいし、実行後の結果を(教師データとして)フィードバックして学習をブーストすることも可能ではないかと目論んでいる。ま、この辺りは確証もない単なる思いつきである。

f:id:interdb:20210729122805p:plain
今後の計画

*1:一応、githubリポジトリ側でも”言い訳”したけども、現代のAIバブルのおかげで、昔は単なる統計学の手法だったものが今では「機械学習です」と大手をふって言えるようなので、遠慮なく言わせてもらう事にした。

Gitの備忘録 (3)

GithubというかGitの使い方。

あるプロダクト(ここではpostgresとする)のリポジトリをclone して、devブランチで独自機能を開発していたとする。 それを新たなリポジトリ(ここではmy-pgsqlとする)に移行して続きを開発する場合の手順。

1. ディレクトリ構成

最初は以下のような状態と仮定する。

$ls /home/vagrant/tmp
postgres
$ cd postgres
$ git branch
* dev
  master

2. 新リポジトリ作成

GitHubに空のリポジトリを作成してcloneしてもよいし、直接git initで作成してもよい。とにかく以下のディレクトリ にリポジトリを作成する。

$ pwd
/home/vagrant/tmp
$ git clone git@github.com:s-hironobu/my-pgsql.git

3. リモートリポジトリの設定

リモートといいつつ、ファイルベースでリポジトリ を指定する。

$ cd my-pgsql
$ git remote add local_repo file:///home/vagrant/tmp/my-pgsql/

4. git pull 実行

あとはgit pullを実行すればよい。pullするブランチ(今回はdev) の指定を忘れずに。

$ git pull dev

5. Githubにpush

Githubにpushする場合、リモートホストを削除して、git pushすればよい。

$ git remote remove local_repo
$ git push

Gitの備忘録(2)

今更のssh対応*1

1. ssh-keyの生成

略。

2. Githubに公開キー設定

略。

3. configファイルの設定

$ cat ~/.ssh/config
Host github.com
     User s-hironobu
     Hostname   github.com
     IdentityFile   ~/.ssh/id_rsa
$ chmod 600 ~/.ssh/config

4. 各リポジトリでの設定

git remte -vで確認して、httpsのままだったら。

$ git remote set-url origin git@github.com:s-hironobu/XXX_REPOSITORY_NAME

*1:他人のリポジトリにpushする場合は、やはり2段階認証が必要なんだろうなあ。携帯など他のデバイスに依存するのも嫌なんだけども。

超超超超ーーーーーーー超絶な嵐

今朝2時頃、突如大粒の雨が降ってきたと思ったら、唐突に物凄い風が吹いてきた。

後から確認すると、時速100km超の超絶豪風で雨も凄まじかった。 20分程度だったと思うが、稲光が毎秒5回くらい発生し、それでも雨がすごいのであまり周囲が明るくならないという、信じられない状況。

写真付きの英語記事が見つからないのでフランス語記事で。 www.swissinfo.ch

https://www.watson.ch/fr/suisse/en%20direct/707448886-transports-a-zurich-bloques-par-l-orage-le-point-dans-toute-la-suisse

redditにもトピックがあった。 https://www.reddit.com/r/Switzerland/comments/oj9x3w/heavy_rain_and_wind_last_night_in_zurich/

当然ながら架線が切れて、トラムは走っていない。

冬の豪雪はまだ「スイスだしありえる」と思ったが、今日の豪風雨は明らかに異常だ。時速100km超の風って。

これによれば、 台風 - Wikipedia 100km/hは台風並みだけども、断じてそんなレベルではなかった。 日本で強いと言われる台風の数倍強かった。 多分100km/h超というのは平均だろう。瞬間最大では200km/hや300km/hを超えたかも。