0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windowsマシン:各種環境でのPython本体の実行速度

Posted at

狙い

EasyISTR(FrontISTR用のGUIツール)のWindows版は、メッシュ変換などが遅いです。
Windows版では、条件の悪いVirtualBoxのLinuxよりも2倍くらい時間がかかり、六面体2次要素が8万個くらいでいらいらする状態になります。
MSYS2のPython3自体の性能がLinux環境と比べて劣るのかを調査しました。

比較した条件

使用したコード

モジュールをインポートしないで(Numpyなどを使わない)、行列の行と列を入れ替えを行う。データは100000行×100列の乱数。Copilotを利用して、Pythonコードを作成。

Modyfy_Matrix.py
#!/usr/bin/env python3
"""
乱数による行列生成および転置処理の速度比較用コード

・行数:1000行、列数:100列
・各要素は線形合同法による擬似乱数(0~1 の浮動小数点数)
・転置処理(行と列を入れ替え)を純粋な Python の二重ループで実施
・計測には __import__("time") を利用しており、トップレベルでの import 文は避けています
"""

def generate_matrix(n_rows, n_cols):
    """
    n_rows 行 n_cols 列の行列を生成する。
    各要素は線形合同法による疑似乱数で生成(0~1 の範囲)
    """
    # 線形合同法の定数(シンプルな例)
    seed = 1
    modulus = 0x7fffffff  # 2^31 - 1
    multiplier = 214013
    increment = 2531011
    matrix = []
    for i in range(n_rows):
        row = []
        for j in range(n_cols):
            seed = (multiplier * seed + increment) & modulus
            row.append(seed / modulus)  # 0~1に正規化
        matrix.append(row)
    return matrix

def transpose(matrix):
    """
    引数 matrix(リストのリスト)の転置を行い、新しい行列として返す。
    """
    n_rows = len(matrix)
    n_cols = len(matrix[0])
    # 転置後の行列は「列数 x 行数」の大きさとなる
    result = [[0] * n_rows for _ in range(n_cols)]
    for i in range(n_rows):
        for j in range(n_cols):
            result[j][i] = matrix[i][j]
    return result

def main():
    # 100000行 x 100列の行列を生成
    matrix = generate_matrix(100000, 100)
    
    # 組み込みの __import__ を利用して time モジュール(計測用)を動的に利用
    perf_counter = __import__("time").perf_counter

    # 転置前の時刻を記録
    start = perf_counter()
    transposed = transpose(matrix)
    # 転置処理終了後の時刻を記録
    end = perf_counter()
    
    print("転置処理にかかった時間: {:.6f} 秒".format(end - start))

if __name__ == '__main__':
    main()

比較した環境と結果

MSYS2自体は、Windows標準やLinuxの環境と比べて、速度が劣ることはありません。
仮想環境(VirtualBoxやHyper-V)ではホストOSとのインターフェースを介するため、実際のハードウェア上で動作するものに比べてオーバーヘッドが大きくなるようです。

Windowsの標準 (Python3.13.2)

.\python
Python 3.13.2 (tags/v3.13.2:4f8bb39, Feb  4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)] on win32

.\python "C:\Users...\Modify_Matrix.py"
転置処理にかかった時間: 0.226710 秒

MSYS2 (Python3.11.7, EasyISTR用の環境)

.\python3
Python 3.11.7 (main, Dec  7 2023, 09:09:57)  [GCC UCRT 13.2.0 64 bit (AMD64)] on win32

.\python3 "C:\...\Modify_Matrix.py"
転置処理にかかった時間: 0.187958 秒

WSL2 / Debian 12のPython3

python3
Python 3.11.2 (main, Nov 30 2024, 21:22:50) [GCC 12.2.0] on linux

python3 Modify_Matrix.py
転置処理にかかった時間: 0.216160 秒

VirtualBox / Ubuntu 22.04のpython3

python3
Python 3.10.12 (main, Feb  4 2025, 14:57:36) [GCC 11.4.0] on linux

python3 Modify_Matrix.py
転置処理にかかった時間: 0.405191 秒

Hyper-V / Ubuntu 22.04のpython3

python3
Python 3.10.12 (main, Feb  4 2025, 14:57:36) [GCC 11.4.0] on linux

python3 Modify_Matrix.py
転置処理にかかった時間: 0.291611 秒

考察

EasyISTRのコードをぱらっとみると、globやmultiprocessingなどWindows環境では、不利となるモジュールがありました。

Copilotが解説してくれたので紹介します。
「WindowsとLinuxの両方で高速に動作させる」のは、手間がかかるようです。

たとえば、multiprocessing モジュールでは、Linux は fork() システムコールを利用できるため、既存のプロセスの状態をそのまま複製することができます。一方、Windows ではプロセスの生成時に新しく Python インタプリタを読み込む必要があり、その結果、初期化オーバーヘッドが大きくなる傾向があります。これが、同じコードでもWindows側で処理開始時に不利になる一因です。
また、glob も内部でファイルシステムのパスを扱う際に、それぞれのOSのファイルシステム特性やエンコーディング、さらにはパターンの解釈方法の違いにより、処理速度に差が出る場合があります。これらのライブラリは基本的に高い汎用性を持ちますが、その反面、OSに最適化された実装になっていないこともあり、特定の環境下では意外なパフォーマンス低下を引き起こすことがあります。
このような状況で「WindowsとLinuxの両方で高速に動作させる」ためのアプローチとしては、以下のような方法が考えられます:

  • OS毎の条件分岐を用いた最適化
    sys.platform や platform.system() で実行環境を判定し、WindowsとLinuxで異なる実装を採用する。たとえば、Windowsでは multiprocessing を使う際に、プロセス生成の初期化を最小化するための工夫や、代替の並列処理モデル(たとえばスレッドや非同期I/O)の検討が挙げられます。
  • ライブラリの選定・利用
    高速なファイルアクセスや並列処理が求められる場合、状況に応じてサードパーティ製のライブラリ(例:pathlib や専用の並列処理ライブラリ、あるいはJITコンパイラを利用するなど)を検討してみるのも良いでしょう。これにより、OS固有の実装差をある程度吸収できます。
  • プロファイリングとボトルネックの特定
    どこに一番時間がかかっているのかプロファイリングして、プラットフォーム毎に最も負荷の高い処理を特定することが重要です。これにより、本当にどの部分が問題なのか、そしてそこをどう最適化すべきかの方向性が見えてきます。
  • 環境に依存しない設計の見直し
    最初からOS固有の挙動に依存しない形でのコード設計を模索することで、両環境でのパフォーマンスの差を小さくできる可能性もあります。たとえば、必要な場合のみ並列化する設計や、ある程度のオーバーヘッドが許容される処理では高速化よりもコードの可読性や保守性を優先する、といった判断が考えられます。

マイナーなノウハウ

VirtualBox

sudo apt install dkms # カーネルアップデート時に失敗するリスクを下げる
# 私は、ゲストOSにHWEカーネルは不要と考えていますので、
# Grub2から古いカーネルを起動してHWE関連は削除しています。
# アップデート時にカーネル関係の設定時間を短縮できます。

cat /etc/group # 共有フォルダを利用する場合。グループ名の確認。
sudo adduser username vboxsf # vboxsfのグループに加わる
# Debian系の場合は、このコマンドでOK

Hyper-V

共有フォルダのファイルのコピー・移動・解凍などは、端末から操作する。

警告
nautilusからパスのコピーはできますが、コピーや移動の操作を行うとフリーズします。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?