Pythonの将来性とJuliaについて

今回はPythonの将来性について、次の3点を軸に解説したいと思います。

  • Pythonとはどんな言語か
  • Pythonの弱点
  • Pythonを取り巻く競合言語

加えて、最近Pythonにとって代わる言語といわれているJuliaについても解説したいと思います。このパートでは、先日オンラインで開催されたJuliaCon2021の発表セッションの例も交えて、Juliaでどんなことができるのかを紹介します。

Pythonとはどんな言語か

https://ja.wikipedia.org/wiki/Python

Pythonとは、どんな言語かというところですが、Wikipediaには上の画像のように書かれています。色々と項目がありますが、赤枠で囲ってある「型付け」と「処理系」という2つの観点からPythonはどんな言語であるかを紐解いていきたいと思います。

型付け

プログラミング言語には、大きく分けて2種類の型付け言語があります。

静的型付け言語
Go言語の例

静的型付け言語は、変数や関数の定義において、型を指定する言語のことを言います。この図のように、xとyはintegerで、この関数が返す値もintegerという風に、あらかじめ型を記述しなければなりません。その点が面倒なのですが、型があらかじめ決まっているので、必要なメモリだけ使用するというように最適化されており、実行速度は速いです。また、コンパイル時に型のチェックを行うので、バグなどの心配が少なく、安全性も高いです。加えて、コードを一目見て、どんな型の変数が使われているのかがわかるので、意思疎通が必要となってくる大規模な開発にも適した言語といえます。

動的型付け言語
Pythonの例

動的型付け言語は、変数や関数の定義において、型を指定しない言語のことを言います。Pythonはこの動的型付け言語に分類されます。この図にあるように、直感的に記述でき、コード量も少なく済むのですが、型が決まっていないため、多くのメモリを必要とします。また、実行時に型の整合性をチェックする必要があるので、実行速度は遅いという特徴があります。このPythonの関数は、型が決まっていないので、数値型以外にもxとyがともにStringやBoolであれば、計算結果を返すことができてしまいます。ポジティブに考えれば柔軟性があるといえますが、一方で意図しない処理になってしまうという心配もあります。

処理系

続いて、処理系についても見ていきたいと思います。処理系には、コンパイル方式とインタープリタ方式があります。

コンパイル方式

コンパイルは、ソースプログラムをいったん機械語に翻訳し、その機械語になったプログラムを実行する方式です。イメージとしては、外国語から日本語に翻訳された本を読む感じです。コードをいったん機械語に直してしまうので、実行速度が速いという特徴があります。一方で、コンパイルした機械語のプログラムは他の環境(OSやCPUが異なると)では実行できないというデメリットもあります。

インタープリタ方式

インタープリタは、プログラミング言語の命令を一つずつ、機械語に解釈しながら実行する方式です。Pythonはインタープリタ方式のプログラミング言語になります。イメージとしては、同時通訳みたいなことをやるものだと考えてください。インタープリタ方式は、環境に左右されず、ソースプログラムをただちに実行できるというメリットがあります。ただ、解釈しながら実行されるために、コンパイル方式に比べると実行速度が遅いです。

Pythonの弱点

Pythonとはどんな言語なのかについて、型付けと処理系の観点から見てきましたが、以上のことからPythonの弱点が3つ挙げられます。

パフォーマンスが低い

Pythonはインタープリタ方式の言語なので、仮想マシンを通さなければならなりません。よって実行速度が遅い言語だと言えます。

モバイルへの適性が低い

Pythonは動的型付け言語なので、多くのメモリを必要とします。そのため、メモリ制約のあるモバイルの開発にはあまり向いていません。

並列処理が苦手

Pythonは並列処理が苦手です。threadingを使えば、並列処理ができないこともありませんが、グローバルインタプリタロックにより、マルチコアプロセッサであってもその恩恵を受けることができません。

Pythonを取り巻く競合言語

次にPythonを取り巻く競合言語について触れたいと思います。

まず、GoやRustの特徴を見ていきましょう。 GoとRustは、 Webアプリ開発や大規模システム開発と主にバックエンドで使用される言語なので、PythonとはWebアプリ開発の用途というところで、競合するのではないかと思います。

GO
特徴
  • 静的型付け言語
  • コンパイル方式
  • シンプルで可読性が高い、並行処理に強い、高速
  • 用途:Webアプリ・サーバ、API開発など

Goはシンプルにかけ、可読性も高く、Pythonの弱点である並列処理や高速な処理を得意としています。

Rust
特徴
  • 静的型付け言語
  • コンパイル方式
  • メモリ安全性、並行処理に強い、C++と同等の速度
  • 用途:大規模システム開発

Rustも、メモリ安全性に優れており、Goと同じく並列処理に強く、速度も速いです。

GoとRustは、 両者とも 静的型付け言語であり、コンパイル方式であります。実は2010年代以降、 GO、Rust、Swift、Kotlinをはじめとする静的型付け言語が多く誕生しています。その背景には、モバイルの発展やシステムの大規模化の波があります。一時期は、PythonやRubyをはじめとする動的型付け言語の生産性が高いということで、主流になったこともあったのですが、 やはり、安定性、メンテナンス性、速度などを考えると静的型付け言語であるGoやRustが今後、主流になっていくのではないかと思います。

Julia
特徴
  • 動的型付け言語:Pythonのようにシンプルに記述できる
  • コンパイル方式(JIT):コード実行前に型推論/最適化を行う
  • 科学技術計算、機械学習、データサイエンス向け
  • 並列処理や分散コンピューティングも視野に入れて設計が行われている
  • Python、C、Fortranのライブラリも使える

Juliaは、今まで紹介してきた言語の中でも特殊で、動的型付け言語でありながら、コンパイル方式 になります。「型付け」で説明したように、動的型付け言語は型を記述する必要がないので、シンプルに記述できます。また、コードの実行前に型推論・最適化を行うので、静的コンパイル言語に近いパフォーマンスを発揮します。物によって差はありますが、大体Pythonの数十倍高速と言われています。用途は、科学技術計算、機械学習、データサイエンス向けで、Pythonが苦手とする並列処理や分散コンピューティングも視野に入れて設計が行われています。Juliaは、あらゆる言語のいいところを集めた感じで、Pythonの弱点をうまくついています。

JuliaCon2021

競合言語について解説してきましたが、中でもJuliaはひと際目立つ存在です。実際にJuliaでどんなことができるのか、Juliaでのプログラミングの一例として、先日オンラインで開催されたJuliaCon2021でのセッションを紹介したいと思います。

Linearly Constrained Separable Optimization

このセッションでは、最適化問題を解くためのパッケージであるPiecewiseQuadratics.jlSeparableOptimization.jlが紹介されています。セッション発表者のEllis Brownさんが所属するBlackRock AI labsが開発しているそうです。

PiecewiseQuadratics.jl

PiecewiseQuadratics.jlは、最適化に特化した一変量の区分二次関数の表現と操作を可能にします。次のような形式の一変量の区分二次関数がある時、p,q,rは任意の値、xは変数です。また、lb, ubはxの下限値、上限値を表します。

実際の例を見てみましょう。5つの区分二次関数がありますが、それぞれ上で見た式に対応していることが分かります。

これらの式をJuliaで扱う際に、 PiecewiseQuadratics.jlを使います。PiecewiseQuadratics.jlでは、以下のように記述することができます。

BoundedQuadraticの引数が、順にlb(xの下限値), ub(xの上限値), p(2次の係数), q (1次の係数) , r (定数) になっています。

さらに、下記のように5つの区分関数からなるグラフを可視化することもできます。

SeparableOptimization.jl

SeparableOptimization.jlはADMMを用いて線形制約のある分離可能な最適化問題を解くことができます。

例えば、次のような二次計画問題がある時、区分関数は fi(xi) にあたります。これはペナルティ関数で x に対して制約を課します。そして、以下の目的関数を最小化する x を求めるのが、この問題になります。

これをSeparableOptimization.jlで実装した例が以下のコードになります。

ここでは制約条件と目的関数の係数について、乱数でデータを作成しています。

区分関数の定義は PiecewiseQuadratics.jl を使う

ここでは、4つの区分関数を定義しています。これからが目的関数のシグマの項にあたる部分になります。区分関数のg1は、x1が[-1, 2]内にあれば2次のペナルティ、x1が[2.5, 3.5]内にあれば1次のペナルティとなりますが、それを可視化すると以下のようになります。

g1の可視化
最適化の実行

ここでは、今まで作成したすべたのパラメータをソルバーに渡して最適化を実行しています。結果として出力されたvars.xが、それぞれx1, x2, x3, x4で、制約条件を満たす値になっていることが分かります。

以上のように、Juliaで二次計画問題を解くことができました。今回紹介したライブラリは、ポートフォリオ最適化や電力効率の最適化などに応用されており、 発表者のEllis Brownさんの論文により詳しい内容が記載されていますので、ぜひそちらもご覧ください。

おわりに

今回は、Pythonの将来性とJuliaについて解説してきましたが、今後Pythonが今の地位を維持できるかどうかは、結局のところ、時代のニーズを取り込めるかどうかによると思います。なぜなら、Pythonが今までそうだったからです。昔から弱点はあったものの、それを上回るだけのニーズ、つまり、AIやデータサイエンスなど、時代に求められてきたからPythonはここまで伸びてきたのだと思います。

今後はどうかというところですが、AIの大規模化に対応していけるかどうかが鍵になってくると思います。Webやシステム開発において、大規模化の波というものがありましたが、AIも同様にどんどん大規模化しています。そうすると、やはり速さや効率性が求められてくるので、Juliaがスタンダードになっていく可能性も十分あります。また、AI の次に来る新しい分野、例えば、確率的プログラミング、微分可能プログラミングなど、そういったニーズも掘り起こしていけるかどうかも重要なポイントになってくるのではないでしょうか。

(K.K)

タイトルとURLをコピーしました