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の偉い方。