はじめに
Qiitaの記事作成で珍しくアイディアが浮かんでこなかったので、Geminiに何かないか聞いてみました
いろいろ質問していくうちに「Pythonについての最新フレームワーク/ライブラリの〇〇を触ってみた!ファーストインプレッションと所感をまとめてみてはいかがでしょう」と提案されました
さらにどんなものがありますかと質問すると「Mojoというものがあります」と言われました
確かになにも知らない聞いたこともないと思ったので、どういったものか、どうやって導入するかを調べてみました
Mojoとは
Mojoは、Modular Inc. によって開発されているプロプライエタリなプログラミング言語です。主な設計者は、Swift言語の生みの親であり、LLVMプロジェクトの主要貢献者でもあるクリス・ラットナー(Chris Lattner)氏です。
Geminiさん様様です
正確にいうとPythonのフレームワークではないみたいですね
ただ、Pythonの構文とセマンティクスを多く取り入れているらしいです
そのほかの特徴としてはPythonは速度が遅いで有名だと思いますが、その欠点を補えているそうです(なんとC/C++やRustに匹敵するほど)
速度が速い理由としては以下のようです
- MojoはMLIRを基盤としているため、特定のハードウェアに最適化されたコードを生成しやすくなっている
- Pythonの動的型付けとは異なり、Mojoでは静的型付けを導入している
- Rustと同様にメモリに対して所有権を導入している
- 複数のデータを同時に処理するSIMD命令を簡単に利用できる機能を組み込んでいる
- PythonのGIL(Global Interpreter Lock)のような制約がなく、マルチスレッドや非同期処理を効率的に記述・実行できる設計になっている
インストール方法
ものは試しでmacbook(Apple M1)にインストールしてみたいと思います
こちらのガイド通りに進めていきます→https://docs.modular.com/max/packages
またHello, Worldを表示するためのサンプルコードも記されていますが、その場合はガイド通り仮想環境を作成した後に、以下資料の2項目から進めるとうまくいくと思います
https://docs.modular.com/mojo/manual/get-started#2-create-a-hello-world-program
(実際にコンパイルしたものを実行するところまで記載されていますね)
Pythonとの差分
Pythonでは型の宣言がいらないですがMojoでは必要です
let
もしくはvar
が必要になります
let
が不変で、var
が可変です
# Mojo: let はイミュータブル (不変) な変数
let x: Int = 10 # 型を明示することも可能
# x = 20 # エラー: 'x' is immutable
# Mojo: var はミュータブル (可変) な変数
var z: Int = 30
print(z)
z = 40 # 再代入可能
print(z)
また、関数の宣言にはdefではなくfnを使用します
# Mojo: fn を使用
fn greet(name: StringRef) -> String:
return "Hello, " + name + "!"
print(greet("Mojo"))
# Pythonのようにデフォルト引数も可能
fn add(a: Int, b: Int = 10) -> Int:
return a + b
print(add(5))
print(add(5, 20))
Mojoでは、引数と戻り値の型を明示することが推奨されるそうです、たしかにコンパイルするのであればそういった情報があった方がより実行速度向上に良い影響がありそうな気はします(コンパイル時にチェックされるそうなのでPythonで型ヒントの書き方を学ぶにはちょうど良い気もします)
ちなみにPythonのdefの書き方にも互換性があるようです
ですがパフォーマンスについてはやはりfnの方がメリットが大きいそうなので、fnに書き換えるのが無難ですね
パフォーマンス比較
気になるPythonとのパフォーマンス性能を確認できればと思います
(Mojoの公式ベンチマークでは、PythonのコードをMojoに書き換えることで、数千倍から数万倍の速度向上を達成した例が示されているそうです)
※Mojoでは「数値計算、並列処理、ハードウェア最適」の領域でメリットが大きいようでCythonなどとの比較だとまた結果は変わるそうです
試しにフィボナッチ数列の計算を行ってみたいと思います
- Python
import time
def fib_py(n: int) -> int:
if n <= 1:
return n
return fib_py(n - 1) + fib_py(n - 2)
start = time.time()
result = fib_py(40)
end = time.time()
print(f"Python fib(40): {result}, Time: {end - start:.4f}s")
- Mojo
fn fib_mojo(n: Int) -> Int:
if n <= 1:
return n
return fib_mojo(n - 1) + fib_mojo(n - 2)
fn main():
print(fib_mojo(40))
結果としては以下のようになりましたMojoの方がtimeコマンドを使って出したので、それぞれ形式が違いますが、確かにMojoの方が結果がすぐに返ってきていることが確認できました
Python fib(40): 102334155, Time: 11.4970s
mojo life.mojo 0.51s user 0.08s system 75% cpu 0.787 total
おわりに
ということでMojoの一部始終でした
計算処理がかなり改善されていたのはとんでもないと思ったのですが、実際にこれをクラウド環境で使えるのかといったところや実際にAPIなど作ることはできるのかまでは調べるところまではいけませんでした
個人的な予想としてはまだまだAPIの作成はFastAPIやDjangoには敵わないのでは?と思っています(使い慣れているだけの可能性も高いと思いますが)
引き続きリファレンスなど読んで活かせる方法を知っていければと思います