背景

なにやらCodonとかいうポケモンみたいなPythonコンパイラがC++並みに速いらしい。
ベンチマークを覗いた感じ、2~200倍くらい?

調べてもJupyter上で使う方法が出てこなかったので、Docker上のUbuntuのJupyterで使えるようにするための備忘録を残しておく。
なお、進捗としてはcodonの形式で書かれたアッカーマン関数のプログラムを動かすまでとする。

参考:
1.Build errors on ubuntu 20.04 LTS
2.あなたのPythonを100倍高速にする技術 / Codon入門

環境

環境としては以下の通り:
PC:Macbook pro 2018 i5
Docker for Desktop: 4.17.0
Image:Jupyter/base-notebookをいじったもの
(Ubuntu22.04,Python3.10(Conda))
前提として、Jupyter環境はすでに整っているものとします。

Codonをビルドする。

めんどくさいことに、Jupyterを使うにはソースからビルドする必要があるらしい。
コンテナ内に入って作業をする。
ビルドにはninjaというものを使っているらしい。C++で書かれているらしいので、c++関連のものと追加で必要そうなライブラリをインストールした。

sudo apt update
sudo apt install -y clang-12 cmake ninja-build libxml2-dev libsodium-dev uuid-dev
git clone --depth 1 -b codon https://github.com/exaloop/llvm-project
cmake -S llvm-project/llvm -B llvm-project/build -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DLLVM_INCLUDE_TESTS=OFF \
    -DLLVM_ENABLE_RTTI=ON \
    -DLLVM_ENABLE_ZLIB=OFF \
    -DLLVM_ENABLE_TERMINFO=OFF \
    -DLLVM_TARGETS_TO_BUILD=all
cmake --build llvm-project/build
cmake --install llvm-project/build

結構時間がかかるので、寝る前とかにやることを推奨。
ただし、Ninjaなどがインストールされていないと失敗するので先にインストールした。
もしエラーが出た際はエラーを調べれば何をインストールすればいいのか大体でてくるので大丈夫だと思われる。
その後、件のプロジェクトをcloneしてくる。
今回はllvm-project下にcodonをcloneしてくる(どこでもいいと思う..)

cd llvm-project
git clone https://github.com/exaloop/codon.git

Jupyterで使うために手直しが必要らしいので、codon/build/_deps/xeus-src/CMakeLists.txtを手直し。参考にしたissueの一部を修正したらbuildが通るようになった。

--- build/_deps/xeus-src/CMakeLists.txt.orig	2022-10-12 18:38:44.000000000 -0700
+++ build/_deps/xeus-src/CMakeLists.txt	2022-10-12 19:55:16.000000000 -0700
.....
.....
 # Dependencies
 # ============
@@ -310,13 +312,15 @@ macro(xeus_create_target target_name linkage output_name)
         if (APPLE)
             target_link_libraries(${target_name} PUBLIC "-framework CoreFoundation")
         else ()
-            if (XEUS_STATIC_DEPENDENCIES)
+            if ((NOT XEUS_USE_DYNAMIC_UUID) AND (XEUS_STATIC_DEPENDENCIES))
+                message(STATUS "static libuuid linking")
                 find_path(LIBUUID_INCLUDE_DIR uuid.h PATH_SUFFIXES uuid)
                 find_library(LIBUUID_LIBRARY libuuid.a)
                 target_include_directories(${target_name} PRIVATE ${LIBUUID_INCLUDE_DIR})
                 target_link_libraries(${target_name} PUBLIC ${LIBUUID_LIBRARY}) 
                 target_link_libraries(${target_name} PUBLIC ${sodium_LIBRARY_RELEASE})
             else ()
+                message(STATUS "dynamic libuuid linking")
                 find_package(LibUUID REQUIRED)
                 target_link_libraries(${target_name} PUBLIC LibUUID::LibUUID)
.....
.....

あとは以下のコマンドでbuildをする。


cmake -S . -B build -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DLLVM_DIR=$(llvm-config --cmakedir) \
    -DCMAKE_C_COMPILER=clang-12 \
    -DCMAKE_CXX_COMPILER=clang++-12 \
    -DCODON_JUPYTER=ON \
    -DXEUS_USE_DYNAMIC_UUID=ON
cmake --build build --config Release 

Jupyterのcodonカーネルを用意する

jupyterは起動できるものとします。
もし準備できていない人は準備してください。

jupyter kernelspec list

で自身のjupyterのカーネルの設定ファイルのPathを確認する。

Available kernels:
  python3    /opt/conda/share/jupyter/kernels/python3

のように表示される場合は、/opt/conda/share/jupyter/kernels/にcodonのカーネル設定を入れたcodonフォルダを作成する。
他の環境の場合は、多分<環境による>/share/jupyter/kernels/になっていると思われる?

cd /opt/conda/share/jupyter/kernels/
mkdir codon
cd codon
touch kernel.json

vimなりnanoなり、好きなテキストエディタでkernel.jsonを作成する。

{
    "display_name": "Codon",
    "argv": [
        "/path/to/codon/build/codon",*****ここをビルドしたcodonへのpathに変更する必要がある。
        "jupyter",
        "{connection_file}"
    ],
    "language": "python"
}

もし/optにllvm-projectをclone/buildし、そのllvm-project下にcodonをclone/buildした場合は以下になる。

{
    "display_name": "Codon",
    "argv": [
        "/opt/llvm-project/codon/build/codon",
        "jupyter",
        "{connection_file}"
    ],
    "language": "python"
}

これで、jupyter環境を再起動することで、codonカーネルを選択することができるようになる。

スクリーンショット 2023-04-04 21.07.44.png

サンプルプログラムを動かす

サンプルプログラムを参考サイトから拝借してきた。

def calc_ackermann():
    import time
    #import sys#Pythonでは必要
    #sys.setrecursionlimit(100000)#Pythonでは必要

    def ackermann(m: int, n: int) -> int:
        if m == 0:
            return n + 1
        elif n == 0:
            return ackermann(m - 1, 1)
        else:
            return ackermann(m - 1, ackermann(m, n - 1))

    m = 3
    n = 11

    t0 = time.time()
    result = ackermann(m, n)
    t1 = time.time()

    print(f"ackermann({m}, {n}) = {result}")
    print(f"elapsed time: {int((t1 - t0) * 1000)} [ms]")
calc_ackermann()
スクリーンショット 2023-04-04 21.09.06.png
スクリーンショット 2023-04-04 21.09.17.png

うーん、速い。

最後に

CodonがJupyterをサポートしてるのに、初期はビルドしてないのは多分ライブラリのライセンス関係っぽいので、今後も必要になってくるかもしれない。

また、Pythonライブラリだが、

export CODON_PYTHON=/path/to/libpython.X.Y.so

で環境せっていしたあとにごにょごにょする必要があるっぽい?

from python import ほにゃらら
or
#pip install codon-jitが必要
import codon
@codon.jit(pyvars=['ほにゃらら'])
def .....

で呼べるらしいがエラーがでてできなかった。

Runtime error: libpython.so: cannot open shared object file: No such file or directory

設定してもうまくいかないし、ビルドし直す必要があるのかもしれない….
もし知っている方がいれば教えてほしいです…

追記

jupyter notebook –generate-configで生成される設定ファイルにos.environ[“CODON_PYTHON”]=/path/to/libpython.X.Y.soみたいな感じで環境変数を設定するようにしたらfrom python import <>が動いた!

广告
将在 10 秒后关闭
bannerAds