中野智文のブログ

データ・マエショリストのメモ

会社の新しいmac book pro に Julia をインストールする

自宅 mac の Julia のインストールには結構時間がかかった。

nakano-tomofumi.hatenablog.com

今回は会社の mac book pro にインストールする。

brew cask install julia でインストー

cask 版を使ったら驚くべきことにサクッとインストールできた。

$ brew cask install julia
==> Satisfying dependencies
complete
==> Downloading https://s3.amazonaws.com/julialang/bin/osx/x64/0.5/julia-0.5.2-osx10.7+.dmg
######################################################################## 100.0%
==> Verifying checksum for Cask julia
==> Installing Cask julia
==> Moving App 'Julia-0.5.app' to '/Applications/Julia-0.5.app'.
==> Linking Binary 'julia' to '/usr/local/bin/julia'.
�  julia was successfully installed!
user@machine:~$ julia
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: https://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.5.2 (2017-05-06 16:34 UTC)
 _/ |\__'_|_|_|\__'_|  |  Official http://julialang.org/ release
|__/                   |  x86_64-apple-darwin13.4.0

うーむ…

julia> Pkg.add("HypothesisTests")
INFO: Initializing package repository /Users/user/.julia/v0.5
....
INFO: Changing Directory to /Users/user/.julia/v0.5/Rmath/deps/src/Rmath-julia-0.1
make -C src
gcc  -Wall -O3 -fPIC -DMATHLIB_STANDALONE -I/Users/user/.julia/v0.5/Rmath/deps/dSFMT   -std=gnu99 -I../include -DNDEBUG -c bd0.c -o bd0.o
...
gcc  -Wall -O3 -fPIC -DMATHLIB_STANDALONE -I/Users/user/.julia/v0.5/Rmath/deps/dSFMT   -std=gnu99 -I../include -DNDEBUG -c randmtzig.c -o randmtzig.o
rm -rf libRmath-julia.dylib
gcc   -shared -o libRmath-julia.dylib bd0.o dnbeta.o i1mach.o pnbinom.o qlnorm.o rgeom.o bessel_i.o dnbinom.o imax2.o pnchisq.o qlogis.o rhyper.o bessel_j.o dnchisq.o imin2.o pnf.o qnbeta.o rlnorm.o bessel_k.o dnf.o lbeta.o pnorm.o qnbinom.o rlogis.o bessel_y.o dnorm.o lgamma.o pnt.o qnchisq.o rmultinom.o beta.o dnt.o lgammacor.o polygamma.o qnf.o rnbinom.o chebyshev.o dpois.o log1p.o ppois.o qnorm.o rnchisq.o choose.o dt.o mlutils.o pt.o qnt.o rnorm.o d1mach.o dunif.o pbeta.o ptukey.o qpois.o rpois.o dbeta.o dweibull.o pbinom.o punif.o qt.o rt.o dbinom.o expm1.o pcauchy.o pweibull.o qtukey.o runif.o dcauchy.o fmax2.o pchisq.o qbeta.o qunif.o rweibull.o dchisq.o fmin2.o pexp.o qbinom.o qweibull.o dexp.o fprec.o pf.o qcauchy.o rbeta.o sign.o df.o fround.o pgamma.o qchisq.o rbinom.o signrank.o dgamma.o fsign.o pgeom.o qexp.o rcauchy.o dgeom.o ftrunc.o phyper.o qf.o rchisq.o stirlerr.o dhyper.o gamma.o plnorm.o qgamma.o rexp.o toms708.o dlnorm.o gamma_cody.o plogis.o qgeom.o rf.o wilcox.o dlogis.o gammalims.o pnbeta.o qhyper.o rgamma.o librandom.o randmtzig.o -L/Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia -ldSFMT
INFO: Changing Directory to /Users/user/.julia/v0.5/Rmath/deps/src/Rmath-julia-0.1
INFO: Package database updated

julia>

おお、問題なくできてそう。

julia> using HypothesisTests
INFO: Precompiling module HypothesisTests.

julia> BinomialTest(24,25)
Binomial test
-------------
Population details:
    parameter of interest:   Probability of success
    value under h_0:         0.5
    point estimate:          0.96
    95% confidence interval: (0.7964830860775859,0.9989878003006891)

Test summary:
    outcome with 95% confidence: reject h_0
    two-sided p-value:           1.5497207641601605e-6

Details:
    number of observations: 25
    number of successes:    24


julia> confint(BinomialTest(24,25))
(0.7964830860775859,0.9989878003006891)

初回起動はちょっと時間がかかったが、ほぼ問題なさそう。自宅での苦労は何だったのか…。

ついでだから、息子の小学校の運動会の得点の信頼区間でも出してみる。

f:id:nakano-tomofumi:20170605192718j:plain

白組と紅組の得点は、1276と1272点だった。本当は団体戦などあるが、1点づつの個人毎の勝敗により点数が加算されたと仮定して、1276+1272=2548 回のベルヌーイ試行のうち、それぞれ、 1276, 1272 の成功があったと考えることにする。

julia> collect(confint(BinomialTest(1276,2548)))*2548
2-element Array{Float64,1}:
 1226.05
 1325.94

白組の95%信頼区間を計算すると、上記のようになる。 1226.05と1325.94の間である。 この失得点差は、非常に僅差であると言えるだろう。ある意味人為的な操作があったとも考えられても不思議ではない。

Airflow をおすすめしない理由

これまでずっと airflow と格闘してきたが(下記参照)

nakano-tomofumi.hatenablog.com

ここで一旦まとめることにする。

Airflow をおすすめしない理由

【致命的】Scheduler がコケる。

タスクは別プロセスで実行されるが、スケジュールもコードで書いてあるためそれを読み込む必要がある。そこで不具合(例えば日本語のコメントなど)があるとコケる。

重複実行されてしまう。

同じタスクIDでも別のDAG IDだと別のタスクとみなされるため、同じジョブが実行されてしまう。

ドキュメントがしっかりしていない。

DAGが paused のことがあったが、そのような話はどこにもなかった。また設定ファイルの重要な項目の説明は、設定ファイル中のコメントに書いてあるだけだったりする。

エラーの出力がしっかりしていない。

何か問題があったときでも、何が原因なのかが分からない。例えば SQLalchemy の一般的なエラーでてもなんの問題か分からない。 その原因を知るためには変数の中身を出力するデバッグコードを埋め込んだりする必要があった。

Airflow と格闘中(14)

nakano-tomofumi.hatenablog.com

のつづき。

エラーで scheduler が落ちる。

次のエラーで落ちる。

Traceback (most recent call last):
  File "/XXX/python/venv/bin/airflow", line 28, in <module>
    args.func(args)
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/bin/cli.py", line 831, in scheduler
    job.run()
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/jobs.py", line 200, in run
    self._execute()
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/jobs.py", line 1311, in _execute
    self._execute_helper(processor_manager)
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/jobs.py", line 1439, in _execute_helper
    (State.SCHEDULED,))
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/utils/db.py", line 53, in wrapper
    result = func(*args, **kwargs)
  File "/XXX/python/venv/lib/python2.7/site-packages/airflow/jobs.py", line 1027, in _execute_task_instances
    open_slots = pools[pool].open_slots(session=session)
KeyError: u'backfill'

普通に考えると、scheduler っていうのは絶対落ちてはNGなのだが、落ちる。

airflow の DAG は設定と実行を同じ pythonファイルで管理している。 scheduler は設定を知るために一旦 DAGファイル・フォルダのpython をすべて読み込む。 backfill では何を読むべきかを指定するのだが、scheduler は何を読むべきかは知らない。よってすべて読むわけである。 これはあくまで予想だが、その読み込んだ全てのファイルのうち、一つでも問題があると、scheduler ごと落ちる。

scheduler は各プロセスの死活監視などを行っているが、自身が死んだら何もならない。crond が死ぬようなものである。

ところで、上記のエラーは DAG ファイルのpool の設定が backfill と書いてあるところをコメントアウトしたら解決した。

webserver をデーモンで起動する

-D オプションをつければいいらしいが、ずっと stdin を待っている。すなわち、デーモンになってない。なぜ? 分からない

とりあえず、コマンドの最後に & をつけよう!

ユニーク制約のエラー

トリガーで試みるも 次のようなエラーが吐かれていた。

[2017-05-31 16:07:15,817] {jobs.py:354} DagFileProcessor3855 ERROR - Got an exception! Propagating...
Traceback (most recent call last):
...
  File "/XXXX/python/venv/lib/python2.7/site-packages/airflow/models.py", line 4117, in verify_integrity
    session.commit()
...
IntegrityError: (pysqlite2.dbapi2.IntegrityError) UNIQUE constraint failed: task_instance.task_id, task_instance.dag_id, task_instance.execution_date [SQL: u'INSERT INTO task_instance (task_id, dag_id, execution_date, start_date, end_date, duration, state, try_number, hostname, unixname, job_id, pool, queue, priority_weight, operator, queued_dttm, pid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'] [parameters: ('task_name', 'dag_name', '2017-05-22 00:00:00.000000', None, None, None, None, 0, u'', 'user_name', None, None, 'bash_queue', 10, None, None, None)]

リトライ中になり、

[2017-05-31 16:12:31,562] {models.py:1126} DagFileProcessor4099 INFO - Dependencies all met for <TaskInstance: dag_name.task_name 2017-05-22 00:00:00 [up_for_retry]>
[2017-05-31 16:12:31,563] {jobs.py:1618} DagFileProcessor4099 INFO - Creating / updating <TaskInstance: dag_name.task_name 2017-05-22 00:00:00 [scheduled]> in ORM

となった後は、 fail した模様。

sqlite> .sch task_instance
CREATE TABLE "task_instance" (
        task_id VARCHAR(250) NOT NULL,
        dag_id VARCHAR(250) NOT NULL,
        execution_date DATETIME NOT NULL,
        start_date DATETIME,
        end_date DATETIME,
        duration FLOAT,
        state VARCHAR(20),
        try_number INTEGER,
        hostname VARCHAR(1000),
        unixname VARCHAR(1000),
        job_id INTEGER,
        pool VARCHAR(50),
        queue VARCHAR(50),
        priority_weight INTEGER,
        operator VARCHAR(1000),
        queued_dttm DATETIME, pid INTEGER,
        PRIMARY KEY (task_id, dag_id, execution_date)
);
CREATE INDEX ti_state_lkp ON task_instance (dag_id, task_id, execution_date, state);
CREATE INDEX ti_pool ON task_instance (pool, state, priority_weight);
CREATE INDEX ti_dag_state ON task_instance (dag_id, state);
CREATE INDEX ti_state ON task_instance (state);

から、UNIQUE制約は、primary key のみといったところか。中身を見てみると、

sqlite> select * from task_instance where task_id = 'task_name' and dag_id = 'dag_name';
task_name|dag_name|2017-05-22 00:00:00.000000|2017-05-31 16:12:34.099778|2017-05-3116:12:44.141016|10.041238|failed|2|host_name|user_name|161||bash_queue|10|BashOperator|2017-05-31 16:07:19.593213|25148

ということらしい。キューに入ったのは、先程のユニーク制約のエラーの後??? よくわからない。

[2017-05-31 16:07:18,138] {jobs.py:343} DagFileProcessor3857 INFO - Started process (PID=24635) to work on /dag_name.py
[2017-05-31 16:07:18,139] {jobs.py:516} DagFileProcessor3857 INFO - dag_id: None
[2017-05-31 16:07:18,141] {jobs.py:1523} DagFileProcessor3857 INFO - Processing file /dag_name.py for tasks to queue

とはなっている。

つづきは、

nakano-tomofumi.hatenablog.com

Airflow と格闘中(13)

nakano-tomofumi.hatenablog.com

のつづき

pause なんて知らない。

やっと原因の一つが分かった。

stackoverflow.com

DAGが (デフォルトで)pause されていたのだ。でも pause されているなんてどこにも書いていない。 Scheduling & Triggers の項目にも、Tutorial にも、 Quick Start にも。もちろんFAQ にも書かれていない。

このためにかなりの時間を使ったような気がする。

それでもまだ動かない

まだまだなのだよ。

つづく。

nakano-tomofumi.hatenablog.com

Airflow と格闘中(12)

nakano-tomofumi.hatenablog.com

Scheduling & Triggers の To Keep in Mind を読む。

以下を読む。

Scheduling & Triggers — Airflow Documentation

以下超訳(カッコ内は自分の感想)

  • DAG Runstart_date から始まるよ。これは日付をしないときの話かな。(trigger とは関係なさそう。)
  • schedule_interval に基づき、連続した DAG Runs は作成されるよ。(そりゃそうだろうね。)
  • 再実行をするために状態の初期化をするときに覚えていたほうがいい重要なことは、DAG Runの状態も、その実行を triggerするタスクを見に行くかどうかを決定する。 (今はなんの依存もないタスクであってもtrigger_dags で実行されないからとりあえずいいか。)

ここでタスクをアンブロックすることができる方法がある。(おや、ブロックされているの?)

  • UIから…(すみません、まだUIとかのレベルではないのでスキップしします)
  • airflow clear -h はたくさんのオプションがあって次のものを指定できる。 日付の範囲、task_id の正規表現、upstream, downstream の関連(!)、ターゲットタスクのインスタンスの失敗や成功。 (インスタンスというのは実行かな? 失敗しても、idempotent 的には、永遠に失敗だから、状態をクリアしないと再実行されないのかな…って、そんな感じのメッセージは現在のところ見てないのでこのあたりは関係なさそう。ところで upstream やdownstream の状態を削除できるのは、luigi ではできなかったことなので、でかい気がするなー。)
  • UIを通してタスクを成功とマークすることができる。これは主に誤った失敗(すなわち成功している話)の修正や例えばairflow外から修正するためのものである。
  • CLIのサブコマンド airflow backfill には --mark_success というフラグがあり、日付を指定するのと同様に DAG のsubsection をしているすることを許可する。(ちなみに、--mark_success オプションは上の意味と同じで、実行せずに成功とマークする機能)

で結論。trigger_dag が上手くいかない手がかりは得られなかった。

UI を見る

UI は本当に見れているのか。

airflow webserver -p 8080

みたいな感じで起動。scheduler などとは直接通信をせず、sqlite の中身をみて現状を確認する様子。よって、scheduler が動いていなくてもWebの画面は正常に表示されるし、 trigger_dag のサブコマンドを実行すると、しっかり web 上のステータスもrunningに追加・変更されるので、まるで scheduler が動いているかののような錯覚を覚えるが、 scheduler は webサーバを起動しても特に動くわけではないし、running のステータスも、実は嘘で、running の状態になるように設定されましたくらいの意味。

重要な設定

Google グループ

くそっ、早く気がつくべきだった。

airflow.cfg に下記を設定

[core]
load_examples = False

デバッグコードを埋め込む

以前からあるエラーメッセージ

nakano-tomofumi.hatenablog.com

の原因が何であるかわからない。 すなわち、dag_stats.dag_iddag_run.dag_id は空である、とのことであるが、これは一体どうなっているのか。

調べていくと、jobs.py の関数 process_file が怪しいことがわかった。

そして、実行されるべきDAG の入ったリスト dags は空であることが判明した。 また、何故空なのか、調べると、ターゲットのDAGが、is_paused となっていることが分かった。

つづく。

nakano-tomofumi.hatenablog.com

自宅macのJuliaLang環境を治す(3)

nakano-tomofumi.hatenablog.com

の続き

ちょっと変化があった。

$ brew test -v julia
Testing staticfloat/julia/julia
==> Using the sandbox
/usr/bin/sandbox-exec -f /tmp/homebrew20170526-45995-169fe4y.sb /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby -W0 -I /usr/local/Homebrew/Library/Homebrew -- /usr/local/Homebrew/Library/Homebrew/test.rb /usr/local/Homebrew/Library/Taps/staticfloat/homebrew-julia/julia.rb -v
==> /usr/local/Cellar/julia/0.5.1/bin/julia -e Base.runtests("core")
WARNING: Error during initialization of module CHOLMOD:
ErrorException("could not load library "libcholmod"
dlopen(libcholmod.dylib, 1): Library not loaded: /usr/local/opt/openblas-julia/lib/libopenblasp-r0.2.19.dylib
  Referenced from: /usr/local/Cellar/julia/0.5.1/lib/julia/libcholmod.dylib
  Reason: image not found")
WARNING: Error during initialization of module CHOLMOD:
ErrorException("could not load library "libcholmod"
dlopen(libcholmod.dylib, 1): Library not loaded: /usr/local/opt/openblas-julia/lib/libopenblasp-r0.2.19.dylib
  Referenced from: /usr/local/Cellar/julia/0.5.1/lib/julia/libcholmod.dylib
  Reason: image not found")
     * core                 WARNING: Method definition f(Tuple{Vararg{Int64, #N<:Any}}, AbstractArray{#T<:Any, #N<:Any}) in module Main at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:723 overwritten at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:729.
WARNING: Method definition f() in module JLCall14301 at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:3546 overwritten at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:3556.
WARNING: static parameter T does not occur in signature for bad_tvars at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:4621.
The method will not be callable.
 in  28.85 seconds, maxrss 1427.54 MB
    SUCCESS

--build-from-source が大事

そもそも、せっかく source からコンパイルしたopenblastのライブラリを使ってないのじゃないの? という疑惑がわく。julia 本体も、--build-from-source をつけてインストール。

$ brew reinstall --build-from-source julia
...
🍺  /usr/local/Cellar/julia/0.5.1: 753 files, 140.5MB, built in 8 minutes 8 seconds
$ brew test -v julia
Testing staticfloat/julia/julia
==> Using the sandbox
/usr/bin/sandbox-exec -f /tmp/homebrew20170526-98332-164n2k7.sb /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby -W0 -I /usr/local/Homebrew/Library/Homebrew -- /usr/local/Homebrew/Library/Homebrew/test.rb /usr/local/Homebrew/Library/Taps/staticfloat/homebrew-julia/julia.rb -v
==> /usr/local/Cellar/julia/0.5.1/bin/julia -e Base.runtests("core")
     * core                 WARNING: Method definition f(Tuple{Vararg{Int64, #N<:Any}}, AbstractArray{#T<:Any, #N<:Any}) in module Main at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:723 overwritten at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:729.
WARNING: Method definition f() in module JLCall14301 at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:3546 overwritten at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:3556.
WARNING: static parameter T does not occur in signature for bad_tvars at /usr/local/Cellar/julia/0.5.1/share/julia/test/core.jl:4621.
The method will not be callable.
 in  28.77 seconds, maxrss 1426.77 MB
    SUCCESS

ちょっと時間がかかったけど、インストールは多少の警告は出るもののうまくいったぽい。

めでたしめでたし。

補足

これまでの苦労が全くのムダのようなことが…

nakano-tomofumi.hatenablog.com

自宅macのJuliaLang環境を治す(2)

nakano-tomofumi.hatenablog.com のつづき。

xcode を入れる。

app store にて。

julia を再インストー

$ brew reinstall julia
Error: You have not agreed to the Xcode license. Please resolve this by running:
  sudo xcodebuild -license accept

とでた。そこで上記のコマンドを実行し、再び julia をインストールするのも失敗。

web の話

Can't load module libopenblas · Issue #76 · staticfloat/homebrew-julia · GitHub

やっぱりこういうのしっかり読むべきだよね。

最後の方に、次を実行しろと書いてある。

brew rm --force gcc gfortran openblas-julia arpack-julia suite-sparse-julia && brew update && brew install julia

R と Julia を既にインストールしてしまっているので、エラーが出たが(--force とは何だったか)、先にそれらを消してから、 再度実行すると、無事インストールされる。

ところが、また同じエラー。

$ brew install --HEAD julia
...
==> make prefix=/usr/local/Cellar/julia/HEAD-bac32d3 USE_BLAS64=0 TAGGED_RELEASE_BANNER="homebrew-julia release" FC=/usr/local/bin/gfortran LLVM_CONFIG=llvm-config-3.7 LLVM_VER=3.7.1 LOCALBASE=/usr/local/Cellar/julia/HEAD-bac32d3 USECLANG=1
Last 15 lines from /Users/nakanotomofumi/Library/Logs/Homebrew/julia/02.make:
            new_enter->setMetadata(LLVMContext::MD_dbg, dbg);
                                   ^~~~~~~~~~~~~
/usr/local/Cellar/llvm37-julia/3.7.1_3/lib/llvm-3.7/include/llvm/IR/DebugLoc.h:23:9: note: forward declaration of 'llvm::LLVMContext'
  class LLVMContext;
        ^
/private/tmp/julia-20170525-4774-rwb8x2/src/llvm-lower-handlers.cpp:218:29: error: incomplete type 'llvm::LLVMContext' named in nested name specifier
            sj->setMetadata(LLVMContext::MD_dbg, dbg);
                            ^~~~~~~~~~~~~
/usr/local/Cellar/llvm37-julia/3.7.1_3/lib/llvm-3.7/include/llvm/IR/DebugLoc.h:23:9: note: forward declaration of 'llvm::LLVMContext'
  class LLVMContext;
        ^
3 errors generated.
make[1]: *** [llvm-lower-handlers.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [julia-src-release] Error 2

If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
https://github.com/staticfloat/homebrew-julia/issues

These open issues may also help:
julia quasi-broken after gcc update https://github.com/staticfloat/homebrew-julia/issues/238

うーむ、これもうまくいかない。

よって次のコマンドを実行。

$ brew reinstall --build-from-source openblas-julia

gfortran のコンパイル(gfortran 自身のコンパイルではありませんでした。)でしばらく時間がかかる。おそらく数時間はかかるんじゃないかな。今日はここでおしまい。と思ったらでた。

$ brew reinstall --build-from-source openblas-julia
==> Reinstalling staticfloat/julia/openblas-julia
==> Using Homebrew-provided fortran compiler.
This may be changed by setting the FC environment variable.
==> Downloading http://github.com/xianyi/OpenBLAS/archive/v0.2.19.tar.gz
==> Downloading from https://codeload.github.com/xianyi/OpenBLAS/tar.gz/v0.2.19
######################################################################## 100.0%
==> make FC=/usr/local/bin/gfortran
==> make PREFIX=/usr/local/Cellar/openblas-julia/0.2.19 install
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local,
because Conflicts with openblas in homebrew-science..

If you need to have this software first in your PATH run:
  echo 'export PATH="/usr/local/opt/openblas-julia/bin:$PATH"' >> ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/openblas-julia/lib
    CPPFLAGS: -I/usr/local/opt/openblas-julia/include

/usr/local/opt/openblas-julia/bin や、/usr/local/Cellar/openblas-julia/0.2.19/bin には何もないことを確認 ^^;

つづきは、 nakano-tomofumi.hatenablog.com