Julia, Cabal

前回は思わず julia なんてのも入れちゃったけど、これ入れる時に下働きでllvmとかopen_blasaなんてのも 一緒に入ったんだ。gccを見切ったんですな。

だって、実行スピード命っていう飛ばし屋さん達が開発してますから。お得意の実行時コンパイル いわゆるJITです。ネイティブなコードに落としてスピード出しましょ。ちょいとその威力を 確認。

julia> @time factor(10)
  0.832614 seconds (609.43 k allocations: 13.171 MB, 6.32% gc time)
Dict{Int32,Int32} with 2 entries:
  5 => 1
  2 => 1

julia> @time factor(9696819)
  0.035414 seconds (6.84 k allocations: 175.788 KB)
Dict{Int32,Int32} with 3 entries:
  26713 => 1
  11    => 2
  3     => 1

julia> @time factor(10)
  0.000140 seconds (11 allocations: 512 bytes)
Dict{Int32,Int32} with 2 entries:
  5 => 1
  2 => 1

初回は10を素因数分解するのに0.8秒もかかっています。2回目からは、大きな数の素因数分解 でも劇的に速くなりました。初回は、コンパイルに時間がかかっているんですなあ。

素因数分解繋がりで、primesなんてのも用意されてた。複素数もちゃんとcomplexが用意されててて、 数の体系が出来上がっている。さすが、MITの人達。MITですから当然MITライセンス。 GNU系ライセンスとは、犬と猿の関係ですよ。

上記の実現にはその場でコンパイルが必要。直ぐに思い付くのはgccだけど、諸般の事情から避けたい。 で、採用したのがLLVMコンパイラー。仮想コンピュータ語に翻訳した後、それをネイティブに 変換する。gccだと、仮想コンピュータ語がRTLとかいうLispっぽいのを採用してるけど、 括弧が嫌いな人が居たに違いない。

そうさ、MITはSchemeを使ったSICPの授業を止めて、PythonでSICPの授業をやってる。Juliaが 1.0版になった時には、混乱のPythonを止めて、Juliaに移行するとかしないとか。

llvmのコンピュータ語が下記のように観測出来るよ。ああ、juliaでの関数定義は、数学っぽくも 書けるんです。数学者や統計学者に使ってもらいたいとな。

julia> f(x::Int) = 2x
f (generic function with 1 method)

julia> code_llvm(f, (Int, ))

define i32 @julia_f_21016(i32) {
top:
  %1 = mul i32 %0, 2
  ret i32 %1
}

そして、下記はネイティブの糞石用に変換されたもの。掛け算より足し算の方が速いから、 そっちをこっそり使ってる、ぐらいの事はオイラーでも読めますよ。幾ら糞石嫌いでも!

julia> code_native(f, (Int, ))
        .text
Filename: none
Source line: 1
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
Source line: 1
        addl    %eax, %eax
        popl    %ebp
        ret

糞にまみれる下層な生活やいやだーーーーーって人は、高尚っぽくASTでも眺めていて ください。

julia> code_warntype(f, (Int, ))
Variables:
  x::Int32

Body:
  begin  # none, line 1:
      return (Base.box)(Int32,(Base.mul_int)(2,x::Int32))
  end::Int32

後、何気に便利なのが、@edit。これを使う時は、環境変数EDITORにviを設定しておこう。 (残念ながらemacsを指定しても無視されるようだ)

julia> split("12,34,56", ",")
3-element Array{SubString{ASCIIString},1}:
 "12"
 "34"
 "56"

このsplitどんなコードになってるの? そんな時は

julia> @edit split("12,34,56", ",")
  :
split{T<:AbstractString}(str::T, splitter; limit::Integer=0, keep::Bool=true) =
_split(str, splitter, limit, keep, SubString{T}[])
function _split{T<:AbstractString,U<:Array}(str::T, splitter, limit::Integer, ke
ep_empty::Bool, strs::U)
   :
end
.../share/julia/base/strings/util.jl: unmodified, UNLOCKED, readonly: line 127

と、簡単に定義場所とコードが表示されました。(@editの代わりに @lessも使える。むしろ、こちらの 方が楽だな。)MITの人達の頭の中を覗くには最適なしかけ です。 おいおいと使ってみようかな。

julia on FreeBSD

2年前にjuliaやってた あの時は万次郎を使ってたんだな。FreeBSDは駄目だろうと思っていたら、サポートしてる らしい。

https://github.com/JuliaLang/juliaを見ると 簡単設定で行けるらしい。乗せられたよ。cmakeが必要、llvm36は入っていた。gfortran48も 既に入ってた。大きなものLIBMとかBLASとかLANACKとかGMPとかFFTWあたりは、Make.incを 変更してFreeBSD備え付けを使う選択。

forranのアプリを作る時にエラー。

gmake FC='gfortran48 -Wl,-rpath=/usr/local/lib/gcc48 '

こういう逃げを打った。llvmのincludeが見つからんとの事で、/usr/includeからllvmの所に リンクを貼った。libも同様な対応。

そして最後にエラー

$ gmake FC='gfortran48 -Wl,-rpath=/usr/local/lib/gcc48 '
  :
    LINK usr/bin/julia
/usr/home/sakae/src/julia-0.4.3/usr/lib/libjulia.so: undefined reference to `llvm::Instruction::getAllMetadataImpl(llvm::SmallVectorImpl<std::pair<unsigned int, llvm::MDNode*> >&) const'
/usr/home/sakae/src/julia-0.4.3/usr/lib/libjulia.so: undefined reference to `llvm::LoopPass::createPrinterPass(llvm::raw_ostream&, std::string const&) const'
  :
collect2: error: ld returned 1 exit status
Makefile:76: recipe for target '/usr/home/sakae/src/julia-0.4.3/usr/bin/julia' failed
gmake[1]: *** [/usr/home/sakae/src/julia-0.4.3/usr/bin/julia] Error 1
Makefile:63: recipe for target 'julia-ui-release' failed
gmake: *** [julia-ui-release] Error 2

残念、至極。FreeBSDに備え付けのllvm36じゃなくて、juliaに馴染んだllvmを構築しないと 駄目なんだろうな。

FreeBSDでも ghc + gnuplot

で、前回はfedora23上のGHCにgnuplotを溶け込ませた。(年寄りは、1週間前の事を 思い出して、咀嚼するのであります)博愛主義のオイラーは、FreeBSD上でも 同様な環境を作っておきたい。

juliaでgnuplotはどうしたと言われそう。調べたらjuliaをFreeBSDで動かした猛者はいない ようだ。portsになっていないんだから、何かの理由が有るのだろう。いつの間にか、Linuxで 世が回っているな。

Linuxと言っても、カーネルだけは共通で、後のユーザーランドは、いろいろなものの寄せ集め に過ぎない。それでも人気が有るって事は、みんなが使ってるのを使っておけば御利益有りそうって、 集団心理かしら。

まあいい、何を使おうと自由だから。さて、FreeBSDにgnuplotを入れようとして、pkg install しようとしたら、色々な付属品が付いてきて1G近い状況になると言ってきた。諦めよう。

自前で入れよう。portsからオプション無しを選択すれば良いかな。Makefileを確認したら、

OPTIONS_DEFINE= CAIRO DOCS EXAMPLES GD GRIDBOX PDF THINSPLINES WX X11

これだけの追加/削除指定が可能みたいだ。X11だけを指定しとけば、グラフ表示は出来るな。 しめしめ。早速makeを始めたら、TeXも取りに行ったよ。入っている事が前提になってるらしい。 勘弁してよね。お前を避けたい為に、わざわざportsから入れようとしてるのに。

しょうがないので、workの下に展開/patch当てが終ったソースの所へ下りて言って、自前で configureしたよ。そしてmake。あれ? makeが先に進まないぞ。ああ、こういう時はgmake だった。世の中、Linuxに毒されてますなあ。

快調にコンパイルが進んで、最後のリンクでエラー発生。何とかって言うシンボルが見つからん。 ひょっとして、こういうライブラリーをリンクしたら旨くいくかもって言ってきた。 そんなの、言う前に試してくれよ。

しょうがないので、Makeを修正。やはりエラー。修正箇所を間違えたかと何度も確認。 間違い無いよ。こういう時は状況確認だな。srcの下に下りて行ったら、なんとそこにも Makefileが置いてあるじゃない。や、やられたね。そちらを変更したら無事にコンパイル完了。 後はいつもの野良インストール。どうせ、絵を出すだけですから、細かい事には気を使いませんよ。

cabalからgnuplotをインストール。

$ ghc-pkg list
 :
/home/sakae/.ghc/i386-freebsd-7.10.2/package.conf.d
     :
   data-accessor-0.2.2.7
   data-accessor-transformers-0.2.1.7
   exceptions-0.8.2.1
   gnuplot-0.5.4
   temporary-1.2.0.4
   transformers-compat-0.5.1.4
   utility-ht-0.0.11

Fedoraの時は、この他にもがちゃがちゃと色々な物をインストールしたようだったけど、 これはghcのバージョン違いから来てるの?

こういうことは、思い立ったら調べておくかな。

Cabal

GHCでパッケージをインストールする時はcabalを使う。rubyにgemの構図と一緒。rubyはgemが バンドルされるようになってから、面白みに欠けたので使うのを手控えていた。だって、 旨くインストール出来たら、rubyをてなずけたって気がしてくるじゃないですか。 その楽しみが奪われたら。。。もう尻尾を巻いて逃げ出す、インストールマニアですよ。

その点、cabalは地獄が待ってますから、十分に楽しめますよ。所でcabalってどういう意味? 名前からしてキャバレーみたいだな。ひょっとしてキャバレーで酔っ払ったいきおいで 書いてしまったから、それを記念してかな。辞書で調べたら、キャバレーってcabaretと 綴るみたいだよ。キャバレーって和製英語なのね。で、肝心のcabalは、

【名】(政治的)秘密結社{(せいじてき)ひみつ けっしゃ}、陰謀、徒党、同人グループ

こういう意味らしい。意味深だな。

折角なので、.cabalの下を見ておく。

$ ls ~/.cabal/
config          logs/           share/
lib/            packages/       world

packages/の下にソースが有り、lib/の下がghc様の参照エリアっぽい。 packagesの下にあるhackage.haskell.org/のインデックスファイルが200Mを超える巨大さ。 世界にそんなにHaskellに入れ揚げてパッケージを作ってる人が居るとは、ちょいとびっくり。

取りあえず、落としてきたgnuplot.tgzの中を覗いてみる。 Setup.lhsって、rubyにもそれっぽいのが有ったな。

$ cat Setup.lhs
#! /usr/bin/env runhaskell
> import Distribution.Simple
> main = defaultMain

ghciでコンパイルする仕様?

$ chmod 755 Setup.lhs
$ ./Setup.lhs
no command given (try --help)
$ ./Setup.lhs --help
  :
Usage: Setup.lhs [GLOBAL FLAGS] [COMMAND [FLAGS]]

Commands:
  configure     Prepare to build the package.
  build         Compile all/specific components.
  repl          Open an interpreter session for the given component.
  install       Copy the files into the install locations. Run register.
  copy          Copy the files into the install locations.
  haddock       Generate Haddock HTML documentation.
  clean         Clean up after a build.
  sdist         Generate a source distribution file (.tar.gz).
  hscolour      Generate HsColour colourised code, in HTML format.
  register      Register this package with the compiler.
  unregister    Unregister this package with the compiler.
  test          Run all/specific tests in the test suite.
  bench         Run all/specific benchmarks.
  help          Help about commands.

For more information about a command use
  Setup.lhs COMMAND --help

Typical steps for installing Cabal packages:
  Setup.lhs configure
  Setup.lhs build
  Setup.lhs install

これと同じようなのが、rubyにもpythonにも有ったな。gnuplot.cabalってのが、Setupする 時の仕様書なんだろうね。

どうもそれっぽい。

Library
  Build-Depends:
    filepath >=1.1 && <1.5,
    temporary >=1.1 && <1.3,
    array >=0.1 && <0.6,
    containers >=0.1 && <0.6,
    utility-ht >=0.0.8 && <0.1,
    data-accessor-transformers >=0.2.1 && <0.3,
    data-accessor >=0.2.2 && <0.3,
    transformers >=0.3 && <0.5,
    deepseq >=1.0 && <1.5
  If flag(splitBase)
    Build-Depends:
      process >=1.0 && <1.3,
      time >=1.5 && <1.6,
      base >=2 && <5
  Else
    Build-Depends:
      base >=1.0 && <2

こんなのが定義されてて、地獄の一丁目ですよ。他のモジュールと整合性を取って いないため、あちらが立てば、こちらが立たずっていう構図が簡単に生まれる仕組み。 近頃は、隔離して動かず、砂場政策がお勧めとか。

で、make ghciってやると、簡単に試せるよとも説明が有った。Makefileを覗いてみると

ghci:   ghci-tmp

ghci-tmp:
        ghci -Wall -i:src:dist/build/autogen:os/generic:execute/tmp src/Graphics/Gnuplot/Simple.hs
   :
testbuild:
        runhaskell Setup configure --user -f buildExamples
        runhaskell Setup build
        runhaskell Setup haddock
   :

ghciにもオプションが有るとは知らなかったな。ghciのmanは無くてghcにまとめられていた。iオプションって Finding importsなのね。

make ghciってのは、ちょいと使う為か、debugのお供だな。いろいろ分かって面白い。

hugsでcabal

Cabalと言えば、hugsにも入っていたな。使う時は、-98オプションを指定して、haskell98を 拡張しないと、文句を言われる。

nb7$ hugs -98
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Bugs: http://hackage.haskell.org/trac/hugs
||   || Version: September 2006 _________________________________________

Hugs mode: Restart with command line option +98 for Haskell 98 mode

Type :? for help
Hugs>  :l Distribution.Simple
Distribution.Simple>

早速、以前にやったCSVパッケージをCabalで処理してみたいんだけど、何を起動したらいいの? demosの中にサンプルが入っていた。

nb7$ cat DefaultSetup.lhs
#!/usr/bin/runhaskell
> module Main where
> import Distribution.Simple
> main :: IO ()
> main = defaultMain

オリジナルはこうなってた。上で出てきたのと一緒だな。

nb7$ runhugs -98 DefaultSetup.lhs
DefaultSetup.lhs: No command given (try --help)
nb7$ runhugs -98 DefaultSetup.lhs --help
Usage: DefaultSetup.lhs [GLOBAL FLAGS]
  or:  DefaultSetup.lhs COMMAND [FLAGS]

Global flags:
  -h, -?  --help  Show this help text

Commands:
  configure     Prepare to build the package.
  build         Make this package ready for installation.
  clean         Clean up after a build.
  install       Copy the files into the install locations. Run register.
  copy          Copy the files into the install locations.
  sdist         Generate a source distribution file (.tar.gz or .zip).
  test          Run the test suite, if any (configure with UserHooks).
  haddock       Generate Haddock HTML code from Exposed-Modules.
  pfe           Generate Programatica Project.
  register      Register this package with the compiler.
  unregister    Unregister this package with the compiler.

For more information about a command, try 'DefaultSetup.lhs COMMAND --help'.

ふむ、これもほとんど一緒か。

nb7$ runhugs -98 /home/sakae/DefaultSetup.lhs configure
/home/sakae/DefaultSetup.lhs: csv.cabal:15: Parse of field 'license' failed:

csvのそれは、MITライセンスだった。原Cabalでは

GPL :: License  -- data constructor
LGPL :: License  -- data constructor
BSD3 :: License  -- data constructor
BSD4 :: License  -- data constructor
PublicDomain :: License  -- data constructor

これしか許していない。ええ、:browseしてがーと出て来るやつを、screenのヒストリモードで 戻って確認。

で、MITライセンスを追加したら、少し進んだけど、やっぱりエラー。

nb7$ runhugs -98 /home/sakae/DefaultSetup.lhs configure
/home/sakae/DefaultSetup.lhs: csv.cabal:20: 'Executable' stanza starting with field 'library build-depends'

原Cabalは、依存関係の解決方法が組み込まれていないようです。残念至極。まあ、昔のCabalだから、 しょうがないのかな?

etc

2016年現在のWindows機によるAnacondaを用いたPythonでのデータマイニング環境構築 なんて言うのが有る。IPythonを中心にPythonの精鋭部隊を結集して、Rに対抗しようという 作戦らしい。

Rは統計に特化していて汎用性に欠けるとかで下火になりつつあるとか。Pythonなら人口も 多いし参入障壁が少ない。 やるなら、Pythonですよ。ラズパイも有るしね。