黒木玄 Gen Kuroki Profile picture
私については https://t.co/WbWjr95AmF と https://t.co/P7WOMn2ay1 と https://t.co/ouhJUcBE7E と https://t.co/Zzel9GBOCm を見て下さい。

Sep 12, 2020, 52 tweets

#Julia言語

それはひどい誤解。(他にも沢山変なことを言っている)

変更されたのは、人間が手で入力するREPLでの挙動だけ。
対人間入力仕様が変わっただけ。

include("foo.jl") や julia foo.jl の形式で使用されていたコードは変更無しに以前と同様に動きます。

qiita.com/mametank/items…

#Julia言語

github.com/keizai-seminar…

などで使用されているJupyter notebookでの仕様は、以前から、現在のJuliaのREPLと同じソフトグローバルスコープになっています。

github.com/JuliaLang/IJul…

だからJupyterユーザーには無関係の話題。

#Julia言語 REPLでの仕様も

[ハード] ローカルスコープ内において、「右辺」でグローバル変数名を使うとグローバル変数が参照されるが、「左辺」ではそうならない。左辺で値の変更先として使う場合には global を付ける。

という「安全仕様」で統一することに関する議論↓

github.com/JuliaLang/juli…

#Julia言語 「ローカルスコープ内でグローバル変数の値を変更したければglobalをつける」は分かり易いのですが、教育目的でREPLを使っている人達は、生徒がREPLを使ったとき

s = 0
for k in 1:10
s += k
end
s

で「予想した通りの結果にならない」という問題で困る。続く

#Julia言語 続き。「ローカルスコープ内でグローバル変数の値を変更したければglobalをつける」というルールを生徒に説明して、さらに「その s = 0 のsはグローバル変数になり、例えば函数内に出て来るローカル変数とは異なる」と説明しなければいけない。

これはつらすぎ。続く

#Julia言語 REPLでもハードスコープを採用すると

s = 0
for i in 1:10
s += i
end
s

のsはグローバル変数なので

s = 0
for i in 1:10
global s += i
end
s

と書く必要があるが、

function f()
s = 0
for i in 1:10
s += i
end
s
end

のsはそうではない、という説明が必要。

#Julia言語 Juliaを初めて使う人にとって、その仕様は厳しすぎるということで、REPL内では

[ソフト] グローバル変数の値を変更するために左辺で使うときにglobalをつける必要がない。(雑な説明)

とするようになったのです(Julia v0.6の仕様に戻った)。

#Julia言語 対人間用のREPL内での仕様の変更に過ぎないので、include("foo.jl") や julia foo.jl でコードを実行する場合には影響がありません。

全部を統一する方がプログラミングが専門の人には分かり易いかもしれませんが、Julia初心者やJulia教育係の負担は増えます。

効率よく #Julia言語 で計算するためにはすべての入力を函数に引数の形で渡した方がよいし、グローバル変数に型注釈を付けて使用するのもちょっとアレな感じで避けたい。

グローバル変数を使うのはどうしても必要な場合に限りたい。だから、面倒に感じられる global を付けることは問題にならない。

しかし、それは開発者レベルの話で、 #Julia言語 を超高級電卓のように使いたい人はグローバル変数のさまざまな値を保持しておきたいものだと思います。

だから、REPLやJupyter上では初心者向けの仕様にし、それ以外では「ハード」な仕様にすることには十分な合理性があります。

#Julia言語 ローカル変数sが存在しないとき、

[ソフト] グローバル変数sが存在すれば s=~ でグローバル変数sの値が変更され、存在しなければ s=~ でローカル変数sが作られる

という仕様は危険。グローバル変数の有無で挙動が変わる!

面倒そうでもglobalを付けなければいけない仕様の方が安全。

#Julia言語 Amazonでの対処法は見付けていないのですが、Googleでは

地域:アメリカ合衆国

に設定すると検索上位にJulia言語関係のサイトが表示されるようになります。

あと、デタラメな発言は引用しない方がよいです。

#Julia言語 引用しない方がよいデタラメは添付画像の通り。ほとんどの文が不適切もしくは間違っている。

【Juliaは速度面で(他のインタープリッタと比較して)圧倒的と言うレベルで高速】の「他のインタープリッタと比較して」の部分だけで、本当に何もわかっていないことが分かる。

#Julia言語 は「函数の実行時に just-in-time でネイティブコードにコンパイルして実行する」仕組みです。

実行時に即ネイティブコードまでコンパイルしてくれる環境は他にも沢山あり、現代においては常識の1つでしょう。

google.com/search?q=just-…

#Julia言語 あと、現代の多くのプログラミング言語では、行列計算をOpenBLASやMKLなどの標準的によく使われている高速なライブラリに任せる仕組みになっていることが多いと思う。

Juliaもそうです。

そのようにしているプログラミング言語間で行列計算の速度に違いはないと考えてよいです。

#Julia言語 Juliaに関する【行列はあるが遅いので使わない方がいい】という発言も、見事に何も分かっていないことを証明している発言だと思いました。

#Julia言語 実際にコードを書いて実験してみると、異なる言語間でのスピード比較は単純な話にはならないことがよく分かります。

単純な計算(例えば基本的な行列演算)では、アセンブラまで使うタイプの原始的な最適化は効果的です。そのことはOpenBLASやMKLを使うと非常に実感できる。

続く

#Julia言語 CやFortranだけではなく、部分的にアセンブラまで使うその手の最適化による高速化は、プログラミング言語そのものの力によって高速化したのではなく、最適化を行った人間が偉いということになると思います。

#Julia言語 ちなみに、実験的に、Juliaで行列計算のコードを最適化したら、OpenBLASの9割程度の速さが出た、という話があります。

github.com/Sacha0/GemmDem…

この事実から、単純計算の人間の手による最適化可能性については、JuliaとCやFortranは同じ程度だと考えて良さそうです。

#Julia言語 より複雑な計算の最適化ではどうでしょうか?

私が繰り返し紹介しているMITの講義の宿題の答え(笑)

nbviewer.jupyter.org/github/steveng…

では、scipyなどで使われているFortranで書かれたライブラリの5〜6倍の速さで計算してくれる指数積分函数E₁(z)のJuliaによる実装法が解説されています。

#Julia言語 以前の私は、CやFortranで書かれた特殊函数のライブラリは長年かけてカリッカリに最適化されていると信じていたので、MITでのJuliaを使った講義の宿題の答えを見て非常にびっくりしてしまいました。

Juliaで速くなった理由は「simd」「並列化」のような浅はかな話ではありません!続く

#Julia言語 昔ながらのアルゴリズムの改善によって高速化が実現されています。

原理的には(笑)、CやFortranだけではなく、アセンブラでも(笑)可能な最適化です。

その意味では「Julia自体が速い」という話ではありません(笑)。続く

#Julia言語 しかし、非常に読み易い宿代の答えの解説

nbviewer.jupyter.org/github/steveng…

の内容を理解すれば、Fortranで同じ最適化をやっていなかった理由も想像できます。アセンブラならさらに大変でしょう(笑)。

#Julia言語

#Julia言語 宿題の答えでは、マクロによるコードの自動生成によって、誤差の制御と速度の改善を実現しています。試行錯誤が必要なので、最適化にはマクロと視覚化はほぼ必須。

数値計算におけるコードの自動生成の重要性については↓



#Julia言語 現実に高速に計算してくれるコードを試行錯誤で作成するには、LispやJuliaのようにプログラム自体をデータとして扱うことができて、実行可能なコードを自動生成する仕組みを容易に実現できることが必要です。

さらに試行錯誤の過程では適切な気楽に視覚化できることが重要。

#Julia言語 以上の一見複雑に見えて実は単純な話は、

 CやFortranの方がJuliaより速いと信じている人達は
 どうしてすべてをアセンブラでも書こうとしないのか?

のようにもまとめられると思います(笑)

#Julia言語 この手の話題は興味深いコードの紹介がないとつまらないものになりがち。私は

nbviewer.jupyter.org/github/steveng…

github.com/Sacha0/GemmDem…

を紹介した。前者は最適化の試行錯誤の過程まで見せてくれているので貴重だと思います。

論よりコード!

#Julia言語 基本的な事柄についてデタラメを言いまくっている人は元々は経済セミナー誌の連載で使われたJuliaのコードを動かそうとしていたみたいです。

私がやればnightly buildでも普通に動く(笑)

そのコードの1つをチェックしたら、使っているパッケージのstructの定義の~続く

#Julia言語 続き~仕方が不適切な点を直すだけで倍以上速くなった。本体側の型安定性をチェックしたら全然ダメだったので改善の余地が大きく残っているコードでした。それでも、MATLAB版より30倍以上速い。

明らかに不適切なJuliaのコードの速さをCと比較するのはナンセンスなので注意を要します。

#Julia言語 は公式ドキュメント

docs.julialang.org/en/v1/manual/p…

に「やめろ」と書いてあることをやってしまっても、結構高速に計算してくれます。便利!

しかし、C, C++, Fortranと比較するときには公式ドキュメントに「やめろ」と書いてあることを守っているコードであることを確認してからにするべき。

#Julia言語 公式ドキュメントにも

a = (グローバル変数の値)

function foo()
グローバル変数aを使った計算
end

function bar()
グローバル変数aを使った計算
end

のように書くのは計算速度的にまずいと書いてあるのですが、結構多くの人がやっています。それでも結構速いのですが、~続く

#Julia言語 続き~、公式ドキュメントに「やめろ」と書かれている書き方をせずにもっと効率的なコードを書きたい人は多いと思う。そういう人は以下のリンク先とその直上の部分を見て下さい。

函数の中で使うデータや変更するデータを常に函数に引数として渡すスタイルで、きれいに書けばよい。

#Julia言語 プレイヤーaとbをバトルフィールドfで戦わせて、a, b, f の状態を変化させる函数のJulia風での書き方は

function battle!(a::Player, b::Player, f::BattleField)

end

のようになります。これを一般化すれば他の場合の普通のコードの書き方も分かる。

#Julia言語 はmultiple dispatchを採用しているので、x + y における + メソッドは x の保有物でもないし、y の保有物でもありません。

battle!(a::Player, b::Player, f::BattleField)というメソッドも、a, b, f のどれかの保有物ではありません。

#Julia言語 とC++(など)の本質的な違いについては以下のリンク先の例を参照(リンクしている動画も参照)。

Juliaスタイルのmultiple dispatchでは、他人が作ったパッケージ群を組み合わせて、新たな機能を追加して、自分が保有するリポジトリで公開することが非常に簡単です。

#Julia言語 「CやFortranの方がJuliaより速い」というのは単なる思い込みに過ぎないことを示す実例の追加。

なぜか「すごい人」がJuliaで書き直すと速くなる不思議。

pure Juliaの数値積分パッケージHCubature.jlは、本体がCで書かれているCubature.jlより速いです。

github.com/JuliaMath/HCub…

ぶっちゃけ、古臭い技術を過学習してしまったせいで新しい技術について行けなくなった人たちが、#Julia言語 についておかしな思い込みをあたかも事実であるかのように述べている傾向があると思う。

「すごい人」ではない私のようなライトユーザーにとっては、 #Julia言語 は優れた「グルー言語」(糊言語)の1つ。

他言語で書かれた優れたライブラリ群を楽に組み合わせて使うことができる。C, Fortranで書かれたライブラリだけではなく、Pythonで書かれた膨大なライブラリ群も利用でき、Rも使える。

#Julia言語 に関する話題はその「速さ」に偏りがちなのですが、「速さ」の話だけをしたいなら超人間的なアセンブラ・プログラマを連れてくればよい(笑)。

CやFortranで書かれたライブラリ群だけではなく、PythonやRやffmpegやImageMagickの類を全部貼り合わせた環境を提供してくれている点が重要。

ライトユーザーの立場では、#Julia言語 が裏で何を使っているかはどうでもよい。

沢山の既存の道具を貼り合わせて使うときに、自分で書いたコードの部分が律速段階になるのはつらい。

Juliaで貼り合わせた場合にはJulia自体が速いので、そういう心配に気を使う必要が無くなります。

貼り合わせてに使う言語が遅いと、そのユーザーは、自分で書いたコードの部分が律速段階になっていることに気付いたとき、Cなどでその部分を書き直すことを検討せざるを得なくなります。

そういうことを沢山の人達が強いられて来た。

それは #Julia言語 以前には仕方がないことだったかもしれませんが、Juliaの登場以後は

 暗黒の原始時代には、多くの人達が高速化のために、
 Cなどでの部分的書き直しを無慈悲にも強制されていた

という評価になるのだと思います。

Juliaの本性は高速なグルー言語だと思う。

遅いが気楽に使える言語によるライブラリ群の貼り合わせは、自分で書いた部分が不都合なくらいの律速段階になると、Cなどの高速な言語での書き直しが強制され、実質的に糊の役目を果たさなくなってしまいます。

それに対して、気楽に使える上に高速な言語による貼り合わせは真の貼り合わせになる。

プログラミングのイロハのイは、コードの使い回し(貼り合わせ)の技術です。

汎用性の高い函数はプログラムの基本的な部品になる。

多くの異なる環境で作成された高速なライブラリ群の使い回しにおいて、貼り合わせがうまく行くためには、貼り合わせに使う道具自身も高速であることが重要。

あと、最近では「当たり前」になっているので、わざわざ誰も言及しませんが、#Julia言語 本体だけではなく、その膨大なパッケージ群のソースコードが公開されている点はありがたいです。

適切なコードの書き方がわからない場合に、自分より圧倒的に優れたプログラマによるコードを参考にできる。

#Julia言語 何度も紹介しているpure Juliaの数値積分パッケージの HCubature.jl は扱える値をAbstractFloat型に制限していたのですが、Real型に緩和されていますね。

これはdual numberを使った自動微分を有効にしたい人には必要。

github.com/JuliaMath/HCub…

#Julia言語 「さすがにCやFortranの方がJuliaより速いはずなので、計算速度が真に重要な部分はCやFortranで書くべきである」と言いだけな発言を継続的に見かける。

しかし、そのような発言が何らかの筋の通ったスタイルでされている場合を1つも見たことがない。続く

#Julia言語 単純な計算の繰り返しの徹底した職人芸的な最適化の代表例は数値線形代数のライブラリです。

github.com/Sacha0/GemmDem…
A pure-Julia, BLIS-style dgemm demo

でOpenBLASの9割位の速さが出ているのをみると、そういう領域でさえ、Juliaが使える可能性があるように見えます。続く

#Julia言語 多くのソフトはFortran(やC)で書かれた基本特殊函数ライブラリを使っています。

MITでの宿題の答え

nbviewer.jupyter.org/github/steveng…

にあるJuliaで書いた指数積分函数E₁(z)は、scipyで採用しているFortranで書かれたライブラリの5~6倍の速さで計算してくれます。

#Julia言語 さらにCで書かれた多変数函数の数値積分ライブラリをJuliaで使えるようにして作られたパッケージ

github.com/JuliaMath/Cuba…

よりも、類似のpure Juliaで書かれた数値積分パッケージ

github.com/JuliaMath/HCub…

の方が計算速度が速く、しかも可能な被積分函数の型の範囲が広いです。

#Julia言語 添付画像はMITでの講義スライド

ocw.mit.edu/courses/mathem…

より。少なくとも基本特殊函数の実装に関しては、「C/Fortranの方が速い」という意見は完全に間違っています。

#Julia言語 このような証拠を見せられると、「そんなに速さが重要なら全部アセンブラで書け」という意見が間違っているのと同じことが、C/FortranとJuliaの間で他にも起こっている可能性の方を心配するべきだと思われます。

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling