🛩️

Modular MojoがPythonより68000倍早いのは本当なのか

2024/02/28に公開

はじめに

mojoについては過去の記事でご紹介しました

https://zenn.dev/shintaroamaike/articles/afcbc867db495e

今回の記事ではMojoはPython 3.10.9の68000倍早いと公式のブログで紹介されていますが、
内容を確認します。

3行まとめ

・AIに特化した言語mojoに触れてみる
・Macbook proでマンデルブロ集合の処理時間を見てみる
・mojoでのpandasのloop処理がどれくらい早くなるのか見てみる

概要

https://www.modular.com/blog/mojo-a-journey-to-68-000x-speedup-over-python-part-3

紹介されている記事では、マンデルブロ集合のアルゴリズムを動作させた時の速度で、
環境は、GCP h3-standard-88とのことです。
すでに実行結果が記事内で紹介されているため、今回は実行しません。

https://cloud.google.com/compute/docs/compute-optimized-machines?hl=ja#h3_series

今回の実行環境はこちらのとおりです

Version

mojo 0.70.0
pandas 2.2.1

使用機

Macbook Pro M2 2022
CPU M2
Memory 24GB

Pythonでの実行時

mojoの実行コードに合わせて、960 x 960 で出力しました。

Python実行時は、1.79sでした。

mojoでの実行時

mojoの実行コードは公式のGitにあります。
https://github.com/modularml/mojo/blob/main/examples/mandelbrot.mojo

シングルスレッド時は65倍
8コア時は294倍となりました。

なぜ68000倍?
h3-standard-88は第4世代のIntel Xeon スケーラブル プロセッサが88個
88の並列処理を行っているのでこの速度が出ているということでした。

続いて一般的なループ処理です。
これは期待した結果とはなりませんでした。

pandasのループ処理

データ準備

python

import pandas as pd
df = pd.DataFrame({"data":list(range(500000))})

mojo

def main():
  let pd = Python.import_module("pandas")
  let np = Python.import_module("numpy")

  let data = np.array(np.arange(500000))
  let df =  pd.DataFrame(data, np.arange(500000), ['data'])

numpy arangeで指定する

iterrows

まずは、pandasのループ処理、df.iterrows()でループすると遅い

for index,row in df.iterrows(): 
    row.data

def main():
  for index,row in df.iterrows():
    print(row.data)
expected 'in' after target identifier. Note that target lists are not yet supported.mojo

mojoでのfor文のルール、ターゲットリストは未対応(0.7.0)
https://docs.modular.com/mojo/manual/basics.html#blocks-and-statements

shape

Seriesの生成を避けるパターン

python

for index in range(df.shape[0]): 
    df.data.iloc[index]

mojo

for index in range(df.shape[0]):
    df.data.iloc[index]

3.5秒。遅くなってしまった

numpyで実行するパターン

python

for index in range(df.shape[0]):
    df.data.values[index]

mojo

for index in range(df.shape[0]):
    df.data.values[index]

2.6秒

valuesを先に取得するパターン

tmp = df.data.values
for index in range(df.shape[0]):
    tmp[index]

  let tmp = df.data.values
  for index in range(df.shape[0]):
      tmp[index]

0.842秒

2024/02/28現在、最新バージョン0.7.0
今回の確認では、期待した結果となりませんでしたが、
正式版のリリースを待って、再確認をしたいと思います。

株式会社マインディア テックブログ

Discussion