julia
前回debianをdist-upgradeしたものだから、色々と点検してたんだ。 そしたら、javaが8の世界を脱して11の世界になってた。
debian:~$ java -version openjdk version "11.0.3" 2019-04-16 OpenJDK Runtime Environment (build 11.0.3+7-post-Debian-5) OpenJDK Server VM (build 11.0.3+7-post-Debian-5, mixed mode, sharing)
頼んだ覚えが無いのに更新されてるって事はLibreOfficeからの要請だったのかな? replが使えるそうなので、試してみた。
debian:~$ jshell | Welcome to JShell -- Version 11.0.3 | For an introduction type: /help intro jshell> System.out.println("Hello World"); Hello World jshell> int a = 123; a ==> 123 jshell> a; a ==> 123 jshell> /exit | Goodbye
これで、ちょいと実験しといてOKとなったらコンパイルしてから使うって方針のCommonLisp並みにやっとなったな。(使わんけど)
julia
debianが新しくなったので、記念にjuliaを入れてみる。 何でも、jitで部分コンパイルされて、実行スピードが向上するのが売りらしい。対抗馬は、RとかPythonらしい。後出しじゃんけんだからswiftみたいに、色々研究出来た訳ね。 Juliaの速さを体感する
2016年にもやってたけど、あの頃はまだ安定期間に入っていなくて、ちょいと悩ましい感じだった。(ああ、普通にjuliaなんて検索すると、本当に悩ましいのが出てくるので、lang juliaを指定の事)
The Julia Programming Language
32/64Bit用に用意されてた。もうじき1.2がやってきそうな雰囲気だけど、安定版と言う事で、1.1.1を入れた。 昔からづっと付き合いのある人は、その集大成の長期保証版を使うのが良いとか。
Plots/GR: グラフ package のおすすめ そう、グラフぐらい書けなくちゃ、octaveにも対抗出来ないしね。
csv file
それから、EXCELでも使えると言う、csvファイルを容易に扱える事も重要。jsonとかxmlは外しても、これは必須事項ですな。
julia> using CSV julia> bld = CSV.read("current.csv", header=false) 5439×4 DataFrames.DataFrame │ Row │ Column1 │ Column2 │ Column3 │ Column4 │ │ │ Int64 │ Int64 │ Int64 │ Int64 │ ├──────┼──────────┼─────────┼─────────┼─────────┤ │ 1 │ 12010104 │ 118 │ 73 │ 57 │ : │ 5439 │ 19063021 │ 108 │ 57 │ 63 │
pythonからの集客を目指して、julia応援隊からの提案だな。でも、重そうな装備だな。
標準備え付けの方が、身軽かな。Delimited Files最後の所にあるリンクでソースが見られる。これが何よりの勉強材料。
julia> using DelimitedFiles julia> bld = readdlm("current.csv", ',', Int, '\n'); julia> size(bld) (5457, 4) julia> bld[1,:] 4-element Array{Int32,1}: 12010104 118 73 57
repl
tar玉を取って来て、適当な所に展開。後はPATHを通すだけ。(黒い画面が大好き人間向け) こちらはGUIな人向けかな。 JuliaとJupyterのすすめ
debian:AA$ julia _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.1.1 (2019-05-16) _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release |__/ | shell> cat /etc/debian_version ## press ; to shellmode 10.0 julia> include("path/to/script-name.jl") julia> apropos("pretty-print") Base.repr Base.repr (v1.1) pkg> status Status `~/.julia/environments/v1.1/Project.toml` [336ed68f] CSV v0.5.9 [28b8d3ca] GR v0.40.0 [91a5bcdd] Plots v0.25.3
for emacs
emacs使いは、julia-modeが有る事を期待。無ければ、もぐりの言語です。やる価値無しと思っていたら、ちゃんと有った。 julia-mode,julia-replを入れ、下記の設定をinit.elにする。
(require 'julia-repl) (add-hook 'julia-mode-hook 'julia-repl-mode)
キーバインドは、下記のように少な目に覚える。ってか、指を訓練する。
C-c C-z ;; run julia C-c C-b ;; exec script C-c C-c ;; exec a line C-c C-d ;; document
my first julia
octaveでやった、dictを使ったME差のプログラムがめちゃくちゃ遅かったので、juliaではどうかとやってみる。
# my first julia using DelimitedFiles function ampm(bld) ymdh = bld[:,1]; hi = bld[:,2] am = []; pm = [] for i in eachindex(ymdh) ymd = div(ymdh[i] , 100) if (ymdh[i] % 100) < 12 push!(am, ymd, hi[i]) else push!(pm, ymd, hi[i]) end end reshape(am,2,:)', reshape(pm,2,:)' end function regkv(dh) tt = [] for i in eachindex(dh[:,1]) push!(tt, (dh[i,1], dh[i,2])) end Dict(tt) end function main() bld = readdlm("current.csv", ',', Int, '\n'); am, pm = ampm(bld) da = regkv(am) dp = regkv(pm) res = zeros(Int,2,2) for k in intersect(keys(da),keys(dp)) av = div(da[k] + dp[k], 2) dl = da[k] - dp[k] if (av > 135 && dl > 15) res[1,2] +=1; end if (av <= 135 && dl > 15) res[1,1] +=1; end if (av > 135 && dl<= 15) res[2,2] +=1; end if (av <= 135 && dl<= 15) res[2,1] +=1; end end res end res = main() println(repr("text/plain", res)) println("Total = ",sum(res))
さらっと書けたかと言うとそうでもなくて、試行錯誤しましたよ。取り合えず実行時間の測定をば。
[ham@cent ~]$ time julia test.jl 2×2 Array{Int64,2}: 857 3 1780 68 Total = 2708 real 0m4.017s user 0m2.514s sys 0m1.653s [ham@cent ~]$ time julia test.jl 2×2 Array{Int64,2}: 857 3 1780 68 Total = 2708 real 0m2.057s user 0m1.995s sys 0m0.397s
初回はjulia自身がOSのキャッシュに載っていないので、時間がかかるんだな。2度目からは速くなる。と言っても、2秒じゃねぇ。awkのやつは、爆速だったぞ。
まてまて、juliaはreplが充実してる。と言う事は、一度juliaを立ち上げたら、そこで生活しなさいって事だな。スクリプトをこねくり回して、あーでもない、こーでもないとやる環境なんだな。さすがMIT発だけある。現代風のLisp環境か。
julia> @timev main() 0.009622 seconds (109.07 k allocations: 3.792 MiB) elapsed time (ns): 9622027 bytes allocated: 3976464 pool allocs: 109005 non-pool GC allocs:36 malloc() calls: 32 2×2 Array{Int64,2}: 857 3 1780 68
これがその証拠。これなら十分に速いと言っていいだろう。頭に@が付くやつはマクロだしね。 timevで出てくるやつも、あれにそっくりだな。そう言えば、juliaの根幹部分にpico-schemeだったかが埋め込まれていたな。
自分でコンパイルすると、そのschemeも取り出せるのかな? 暇な時にソースを見てみよう。
で、このコードを作り上げる時、関数を書いてそれをテストし、正しかったら次に繋げて行くって方針でやってた。ボトムアップ方式ね。
そうして、関数を呼び出すコードが、スクリプトの最後の方に溜まってこれで佳しとなった時に、溜まったコードを function main()で一括りにしたんだ。(mainの外側に、結果の表示コードが置いてあるけど、それはご愛嬌です。)
Dict
辞書を作りたかったんだけど、動的に作る方法をサッと見つけられなかった。そこで、helpしてみた。
help?> Dict search: Dict IdDict WeakKeyDict AbstractDict redirect_stdin redirect_stdout : Examples ≡≡≡≡≡≡≡≡≡≡ julia> Dict([("A", 1), ("B", 2)]) Dict{String,Int64} with 2 entries: "B" => 2 "A" => 1 Alternatively, a sequence of pair arguments may be passed. julia> Dict("A"=>1, "B"=>2) Dict{String,Int64} with 2 entries: "B" => 2 "A" => 1
ネットを検索しても、例2の例ばかり。Dictって余り人気が無いのでしょうか? とにかく、タプルの配列を食わせれば良い事が分かった。
そんなこんなで、上記の様なコードが生まれた訳だけど、eachindexを使ってループを回しているのが、いかにも遅いぞって信号を発してるようで、気分が悪い。
kとvに相当するものをindex経由じゃなくて、ずばっと取り出せないか?
julia> a = ["a", "b", "c"]; julia> for (index, value) in enumerate(a) println("$index $value") end 1 a 2 b 3 c
これじゃ、意味無いしね。juliaが衣を被ったLispって事を思い出して、まとめてくれる関数を脳内サーチ。
julia> a = [1 2 3] 1×3 Array{Int32,2}: 1 2 3 julia> b = [5 6 7] 1×3 Array{Int32,2}: 5 6 7 julia> Dict(zip(a,b)) Dict{Int32,Int32} with 3 entries: 3 => 7 2 => 6 1 => 5
ぴったりぽい。
function regkvt(dh) Dict(zip(dh[:,1],dh[:,2])) end
コードにしたら、こんなにすっきりした。juliaは、マトリックスのアクセスは列方向優先で行われるそうなので、スピードアップを期待。
julia> @timev regkvt(am) 0.000493 seconds (9.79 k allocations: 287.781 KiB) elapsed time (ns): 492823 bytes allocated: 294688 pool allocs: 9778 non-pool GC allocs:5 malloc() calls: 4 Dict{Any,Any} with 2721 entries: 170921 => 142
こちらは、既存の長ったらしいやつ。
ulia> @timev regkv(am) 0.001337 seconds (16.37 k allocations: 561.609 KiB) elapsed time (ns): 1337348 bytes allocated: 575088 pool allocs: 16353 non-pool GC allocs:10 malloc() calls: 3 Dict{Int64,Int64} with 2721 entries: 170921 => 142 :
1.3msかかっていたのが、0.5msに高速化した。メモリー使用量も大幅に減っている。
Profile
統計的なプロファイラーが装備されてるとか。スクリプトを実行して、1msの間隔でバックトレースし、どこを実行してたか集積する。短い実行時間だとかすりもしないので、何回も実行すれば、そのうちに当たるでしょって方針。よって、スクリプトに手を入れる必要は無い。
julia> @profile (for i=1:1000; regkvt(am); end) julia> Profile.print() 13 ./dict.jl:305; ht_keyindex2!(::Dict{Any,Any}, ::I... 4 ./dict.jl:318; ht_keyindex2!(::Dict{Any,Any}, ::I... : 2 ./array.jl:729; getindex 2 ./sysimg.jl:18; getproperty 3 ./tuple.jl:24; iterate julia> Profile.print(format=:flat) Count File Line Function 1193 ./REPL[5] 1 macro expansion 338 ./abstractarray.jl 927 getindex : 1193 ...b/v1.1/REPL/src/REPL.jl 117 macro expansion 1193 /tmp/AA/test.jl 28 regkvt(::LinearAlgebra.Adjoint{Any,A... 2 .../julia/lib/julia/sys.so -1 hashindex(::Int32, ::Int32) 8 .../julia/lib/julia/sys.so -1 isequal(::Int32, ::Int32)
走らせた後、2種類の方法で、結果を眺められる。
もっとかっこよく眺めたいなら、GUI版も用意されてるぞ。
Benchmark
大体、@timev とかで用事が足りると思うけど、論文を発表したい時とかに使うのかな?
Debugger
以前にjuliaした時は、無かったような。遂にこういう物もリリースされるようになったのね。 感慨深い。って、言う程使っていないだろに!
目ざとい人が居て、日本語解説をされてた。これが役にたつのは何時だろう?
btがサポートされてるようだから、結構役にたつかな。それはそうと、schemeのRnRSでは必須とされている、traceって無いものだろうか? >MITの偉い方。