パラレルログpython-mpi-logger

8472 ワード

前回ではIPythonでmpi 4 pyを使用する方法について説明しましたが、mpi 4 pyを使用して実装されるパラレルログツールであるpython-mpi-loggerについて説明します.
python-mpi-loggerを紹介する前に、python-mpi-loggerもloggingモジュールのフレームワークの下にあるため、ログの概念とその役割、Python標準ライブラリが提供するログ記録loggingモジュールについて簡単に紹介します.
ログ(log)
ログ(log)は、ソフトウェアの実行中に発生したイベントを追跡する方法です.ソフトウェア開発者は、コードにログ記録に関連するメソッドを呼び出して、何かが起こったことを示すことができます.1つのイベントは、オプション変数データを含むメッセージで記述できます.また,イベントにも重要性の概念があり,この重要性を重大度レベル(level)と呼ぶこともできる.
ログの分析を通じて、ユーザーがシステムやソフトウェア、アプリケーションの運行状況を理解するのに便利である.アプリケーションログが十分に豊富であれば、従来のユーザーの操作行為、タイプの好み、地域分布、その他の情報を分析することもできます.1つのアプリケーションのログが同時に複数のレベルに分かれている場合、そのアプリケーションの健康状況を簡単に分析し、問題をタイムリーに発見し、迅速に位置決めし、問題を解決し、損失を救済することができます.簡単に言えば、ログの記録と分析によって、システムまたはソフトウェアプログラムの動作が正常であるかどうか、アプリケーションに障害が発生した場合に問題を迅速に特定することができます.
ログの役割は、以下の3つに簡単にまとめることができます.
  • プログラムデバッグ;
  • ソフトウェアプログラムの運行状況、正常かどうかを知る.
  • ソフトウェアプログラムは故障分析と問題位置決めを実行します.

  • Python loggingモジュール
    Python標準ライブラリのloggingモジュールで定義された関数とクラスは、アプリケーションとライブラリの開発に柔軟なイベントログシステムを実現しています.loggingモジュールはPythonの標準ライブラリモジュールであり、標準ライブラリモジュールによってログ記録APIを提供する利点は、すべてのPythonモジュールがこのログ記録機能を使用できることである.したがって、アプリケーション・ログは、サードパーティ・モジュールからの情報と独自のログ情報を統合することができます.
    loggingモジュールには、次の基本クラスがあります.
  • Loggerオブジェクト:アプリケーションが直接使用するログインタフェースを提供する;
  • Handlerオブジェクト:ログ記録(Loggerオブジェクトによって生成される)を適切な宛先に送信する.
  • Filterオブジェクト:最終的に出力されるログを細かく制御します.
  • Formatterオブジェクト:最終出力ログのフォーマットを制御します.

  • 以下にloggingモジュールの主要クラスとモジュールレベル関数の使用インタフェースを示します.詳細は、そのドキュメントを参照してください.
    Loggerクラス
    注意:ロガークラスオブジェクトを直接初期化するのではなく、モジュールレベル関数loggingを使用します.getLogger(name)は、新しいLoggerオブジェクトを生成するか、既存のLoggerオブジェクトを返す.
    次に、主なメソッドインタフェースを示します.
    Logger.setLevel(level)
    

    ログレベルをlevelに設定します.levelより低いレベルのログ・メッセージは無視されます.次に、事前定義されたログ・レベルと対応する数値を示します.
    等級

    CRITICAL
    50
    ERROR
    40
    WARNING
    30
    INFO
    20
    DEBUG
    10
    NOTSET
    0
    Logger.debug(msg, *args, **kwargs)
    

    DEBUGレベルでログを記録します.msgはログ・メッセージのフォーマット文字列であり、argsmsgにマージされる関連パラメータである.簡単なルーチンは次のとおりです.
    FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
    logging.basicConfig(format=FORMAT)
    d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
    logger = logging.getLogger('tcpserver')
    logger.debug('Protocol problem: %s', 'connection reset', extra=d)
    

    生成する出力は、2006-02-08 22:20:02165 192.168である.0.1 fbloggs Protocol problem: connection reset
    Logger.info(msg, *args, **kwargs)
    

    INFOレベルでログを記録します.パラメータはdebug()と同じです.
    Logger.warning(msg, *args, **kwargs)
    

    WARNINGレベルでログを記録します.パラメータはdebug()と同じです.
    Logger.error(msg, *args, **kwargs)
    

    ERRORレベルでログを記録します.パラメータはdebug()と同じです.
    Logger.critical(msg, *args, **kwargs)
    

    CRITICALレベルでログを記録します.パラメータはdebug()と同じです.
    Logger.log(lvl, msg, *args, **kwargs)
    

    整数値lvlをレベルとしてログを記録します.その他のパラメータはdebug()と同じです.
    Logger.addFilter(filter)
    

    このLoggerにFilterオブジェクトfilterを追加します.
    Logger.removeFilter(filter)
    

    このLoggerからFilterオブジェクトfilterが削除される.
    Logger.addHandler(hdlr)
    

    ロガーにHandlerオブジェクトhdlrを追加します.
    Logger.removeHandler(hdlr)
    

    ロガーからHandlerオブジェクトhdlrを削除します.
    Handlerクラス
    注意:通常、Handlerクラスオブジェクトは直接初期化されません.Handlerクラスの目的は,より有用なサブクラスのベースクラスとして,そのサブクラスの_init__()メソッドでHandlerを呼び出す必要があります.init__().
    次に、主なメソッドインタフェースを示します.
    Handler.__init__(level=NOTSET)
    

    レベルlevelでHandlerオブジェクトを初期化します.
    Handler.setLevel(level)
    

    このHandlerオブジェクトのログレベルをlevelに設定します.levelより低いレベルのログ・メッセージは無視されます.
    Handler.setFormatter(fmt)
    

    HandlerオブジェクトのFormatterをfmtに設定します.
    Handler.addFilter(filter)
    

    HandlerオブジェクトにFilterオブジェクトfilterを追加します.
    Handler.removeFilter(filter)
    

    HandlerオブジェクトからFilterオブジェクトfilterを削除します.
    Handler.emit(record)
    

    このメソッドでは、実際のログを記録する作業を完了します.サブクラスは、この方法を具体的に実装する必要があります.
    Python標準ライブラリには、直接使用できるhandlerがいくつか含まれています.これらのhandlerのリストはloggingを参照してください.handlers.
    モジュールレベル関数
    次に、主なモジュールレベル関数インタフェースの一部を示します.
    logging.getLogger([name])
    
    nameが指定されている場合、nameという名前のloggerが返されます.そうでない場合、そのloggerレベルのルートloggerが返されます.同じnameでこの関数を呼び出すと、同じloggerオブジェクトが返されます.
    logging.debug(msg[, *args[, **kwargs]])
    

    DEBUGレベルでログを記録します.msgはログ・メッセージのフォーマット文字列であり、argsmsgにマージされる関連パラメータである.
    logging.info(msg[, *args[, **kwargs]])
    

    INFOレベルでログを記録します.パラメータはdebug()と同じです.
    logging.warning(msg[, *args[, **kwargs]])
    

    WARNINGレベルでログを記録します.パラメータはdebug()と同じです.
    logging.error(msg[, *args[, **kwargs]])
    

    ERRORレベルでログを記録します.パラメータはdebug()と同じです.
    logging.critical(msg[, *args[, **kwargs]])
    

    CRITICALレベルでログを記録します.パラメータはdebug()と同じです.
    logging.log(level, msg[, *args[, **kwargs]])
    

    整数値lvlをレベルとしてログを記録します.その他のパラメータはdebug()と同じです.
    logging.basicConfig([**kwargs])
    

    この関数は、StreamhandlerとデフォルトのFormatterを作成し、ルートloggerに追加し、このloggerの基本的な設定を行います.ルートloggerにhandlerが指定されていない場合、関数debug()、info()、warning()、error()およびcritical()はbasicConfig()を自動的に呼び出します.
    python-mpi-logger
    python-mpi-loggerはmpi 4 pyを使用する並列ログツールであり、標準ライブラリから継承するloggingであるMPILogHandlerクラスを提供する.Handlerクラスは、このhandlerモジュールを使用して、MPIパラレルプログラムのログを安全かつ効率的に記録することができる.MPILogHandlerクラスの基本的な動作原理は、プログラムを実行するMPIプロセスが、親MPIプロセスのすべてのloggingモジュールによって生成されたメッセージを収集し、収集されたメッセージを指定された日志文書に書き込むサブMPIプロセスを生成することである.
    ここでダウンロードしてpython-mpi-loggerをインストールできます.ダウンロードとインストールのコマンドは次のとおりです.
    $ git clone https://github.com/jrs65/python-mpi-logger.git
    $ cd python-mpi-logger
    $ python setup.py install [--user]
    

    次はmpiloggerです.MPILogHandlerクラスの定義およびメソッドインタフェース:
    class MPILogHandler(logging.Handler)
    

    MPILogHandlerクラスは、標準ライブラリからのloggingを継承する.Handler.
    def __init__(self, logfile, comm=None, *args, **kwargs)
    

    初期化方法は、logfileがログファイル、commがmpi 4 pyである.MPI.Intracomm通信子、デフォルト値None、MPIを使用することを示す.COMM_WORLD.このメソッドではcomm.Spawnメソッドが呼び出され、新しいサブプロセスが生成されます.
    def emit(self, record):
    

    リロードlogging.実際にログを記録する作業を完了するHandlerクラスの同じ名前のメソッド.具体的には、すべての親MPIプロセスは、新しく生成されたサブプロセスに自分のログを送信し、サブプロセスは、受信するとlogfileにログを書き込む.recordはLogRecordオブジェクトであり、このメソッドはクラスを初期化する際に使用される通信子のrankとsizeをrecordの同名属性に付与するので、formatterでこの2つの属性を使用することができる.
    ルーチン
    python-mpi-loggerを使用してパラレルログを記録する方法は、標準ライブラリのloggingモジュールを使用してログを記録する方法と基本的に同じです.python-mpi-loggerは追加のhandlerを提供しているだけなので、MPILogHandlerオブジェクトを初期化し、loggerオブジェクトに追加すればいいだけです.次に、簡単な使用例を示します.
    # mpi_logger.py
    
    """
    Demonstrates the usage of python-mpi-logger package.
    
    Run this with 2 processes like:
    $ mpiexec -n 2 python mpi_logger.py
    """
    
    import logging
    from mpi4py import MPI
    import mpilogger
    
    
    # the communicator
    comm = MPI.COMM_WORLD
    
    # get the logger
    logger = logging.getLogger('mpitestlogger')
    
    # initialize a MPILogHandler object
    mh = mpilogger.MPILogHandler('testlog.log', comm=comm)
    
    # construct an MPI formatter which prints out the rank and size
    mpifmt = logging.Formatter(fmt='[rank %(rank)s/%(size)s] %(asctime)s : %(message)s')
    mh.setFormatter(mpifmt)
    
    # add the handler to the logger
    logger.addHandler(mh)
    
    # iterate through and log some messages
    for i in range(2):
        logger.warning("Hello (times %i) from rank %i (of %i)" % (i+1, comm.rank, comm.size))
    

    生成されたログファイルtestlog.ロゴの内容は以下の通りです.
    [rank 0/2] 2018-11-01 21:21:02,138 : Hello (times 1) from rank 0 (of 2)
    [rank 1/2] 2018-11-01 21:21:02,138 : Hello (times 1) from rank 1 (of 2)
    [rank 0/2] 2018-11-01 21:21:02,187 : Hello (times 2) from rank 0 (of 2)
    [rank 1/2] 2018-11-01 21:21:02,187 : Hello (times 2) from rank 1 (of 2)
    

    以上、python-mpi-loggerというパラレルログツールについて説明しました.次の記事では、パラレルフーリエ変換パッケージであるmpi 4 py-fftについて説明します.