🚀

【wsl+Ubuntuで数値解析】プログラムをUbuntu直下のディレクトリに保存して実行速度を高速化した

2024/01/08に公開

実施内容

  • wsl2において,Windows11のデスクトップに保存した自作の有限要素法プログラムを実行すると,計算の途中でCPU稼働率が20~30%程度しか使用できず,処理が遅くなる現象を確認しました.
  • そこで,ファイルの入出力が原因と判断し,wsl2にインストールしたUbuntuのホームディレクトリ直下にプログラムを保存するようにしました.
  • サンプルプログラムを作成し,実際の効果を検討しました.

やってみた結果

  • Ubuntuのホームディレクトリ直下に保存したプログラムでは,ファイル出力時のCPU稼働率が80%程度となり,処理速度が向上しました.
  • wsl2では,UbuntuとWindows間でのファイルのやり取りに処理速度上の問題があることを確認しました.
  • Windows直下には,プログラムを保存しない方針としました.

検討環境とPCスペック

  • Windows11
  • wsl2
  • Ubuntu
  • CPU:Intel i9-10900K
  • メモリ:32GB

事前準備

  • 検討を行うためのサンプルプログラムをC++にて作成しました.プログラムは,単純な行列積を計算し,結果をテキストファイルに出力するものです.
  • 関数parallelMatrixMultiplication()にて行列積を計算しています.ここでは,OpenMPによる並列計算を適用します.
  • 関数writeMatrixToFile()にて結果のファイル出力を行います.計算時間の差がわかりやすいように,テキストファイルへの出力は同じ処理を繰り返し行うようにしています.
test.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <omp.h>

void parallelMatrixMultiplication(const std::vector<std::vector<int>>& matrixA,
                                  const std::vector<std::vector<int>>& matrixB,
                                  std::vector<std::vector<int>>& result) {
    #pragma omp parallel for
    for (size_t i = 0; i < matrixA.size(); ++i) {
        for (size_t j = 0; j < matrixB[0].size(); ++j) {
            result[i][j] = 0;
            for (size_t k = 0; k < matrixB.size(); ++k) {
                result[i][j] += matrixA[i][k] * matrixB[k][j];
            }
        }
    }
}

void writeMatrixToFile(const std::string& filename, const std::vector<std::vector<int>>& matrix) {
    std::ofstream file(filename);
    if (file.is_open()) {
        for (const auto& row : matrix) {
            for (const int& element : row) {
                file << element << " ";
            }
            file << "\n";
        }
        file.close();
    } else {
        std::cerr << "Unable to open file: " << filename << std::endl;
    }
}

int main() {
    const size_t size = 2000;
    const std::string resultFilename = "result.txt";
    
    // 行列の初期化
    std::vector<std::vector<int>> matrixA(size, std::vector<int>(size, 1));
    std::vector<std::vector<int>> matrixB(size, std::vector<int>(size, 2));
    std::vector<std::vector<int>> result(size, std::vector<int>(size, 0));

    // 並列な行列の乗算
    double start_time = omp_get_wtime();
    parallelMatrixMultiplication(matrixA, matrixB, result);
    double end_time = omp_get_wtime();

    // 結果の表示
    std::cout << "Execution time: " << end_time - start_time << " seconds" << std::endl;

    // 結果をファイルに保存
    double start_time2 = omp_get_wtime();
    for(int i=0;i<100;i++) writeMatrixToFile(resultFilename, result);
    double end_time2 = omp_get_wtime();
    
    // 結果の表示
    std::cout << "output text data time: " << end_time2 - start_time2 << " seconds" << std::endl;

    return 0;
}
  • コンパイルの方法は以下の通りです.OpenMPを使用するため,-fopenmpが必要です.
gcc -fopenmp test.cpp
  • 通常通りプログラムを実行します.
./a.out

プログラムの実行結果

  • 同じプログラムをWindowsのデスクトップに保存した場合とUbuntuのホームディレクトリに保存した場合それぞれのCPU稼働率と処理時間を比較しました.
  • 結果は,同じ条件で3回ずつ計算を行い,その平均値を示しています.
  • CPU稼働率は,時々刻々変化するため,ある一瞬の値を示しています.

行列積の計算

  • CPU稼働率,計算時間ともに大きな差はありませんでした.
  • つまり,この部分は,保存場所は処理速度に関係ないようです.
プログラムの保存場所 CPU稼働率 [%] 計算時間 [sec]
Windows デスクトップ 1998 14.3
Ubuntu ホームディレクトリ 1996 14.4

テキストファイルへの出力

  • Ubuntuに直接保存することで,CPUを効率的に使用し,計算時間は1/2倍以下となりました.
  • 数値解析では,大規模なデータを出力することが多いため,この差がより顕著になるといえます.
プログラムの保存場所 CPU稼働率 [%] 計算時間 [sec]
Windows デスクトップ 39.0 62.8
Ubuntu ホームディレクトリ 81.0 28.3

参考

まとめ

  • プログラムの保存場所が処理速度に影響するとは気が付かず,困っていましたが,今回で解決できました.
  • プログラムは,github+VSCodeで開発すれば,UbuntuであってもWindows上で管理する方法と同じようにプログラムを管理できます.運用方法については,いつか別の記事で書けたらと思います.

Discussion