14

計算科学の典型的な状況は、数日/数週間/数か月連続して実行されるプログラムを持つことです。ハードウェア/OS の障害は避けられないため、通常はチェックポイントを利用します。つまり、プログラムの状態を時々保存します。失敗した場合は、最新のチェックポイントから再起動します。

チェックポイントを実装するPythonicの方法は何ですか?

たとえば、関数の変数を直接ダンプできます。

または、そのような関数をクラスに変換することを考えています(下記参照)。関数の引数は、コンストラクターの引数になります。アルゴリズムの状態を構成する中間データは、クラス属性になります。モジュールpickleは(非)シリアル化に役立ちます。

import pickle

# The file with checkpointing data
chkpt_fname = 'pickle.checkpoint'

class Factorial:
    def __init__(self, n):
        # Arguments of the algorithm
        self.n = n

        # Intermediate data (state of the algorithm)
        self.prod = 1
        self.begin = 0

    def get(self, need_restart):
        # Last time the function crashed. Need to restore the state.
        if need_restart:
            with open(chkpt_fname, 'rb') as f:
                self = pickle.load(f)

        for i in range(self.begin, self.n):
            # Some computations
            self.prod *= (i + 1)
            self.begin = i + 1

            # Some part of the computations is completed. Save the state.
            with open(chkpt_fname, 'wb') as f:
                pickle.dump(self, f)

            # Artificial failure of the hardware/OS/Ctrl-C/etc.
            if (not need_restart) and (i == 3):
                return

        return self.prod


if __name__ == '__main__':
    f = Factorial(6)
    print(f.get(need_restart=False))
    print(f.get(need_restart=True))
4

3 に答える 3

4

通常、答えは、cpickle json または xml などのお気に入りのシリアル化方法でシリアル化することです。Pickle には、余計な作業をせずにオブジェクト全体を逆シリアル化できるという利点があります。

さらに、プロセスを状態から分離することをお勧めします。これにより、状態オブジェクトを単純にシリアル化できます。スレッドなどの多くのオブジェクトはピクルできませんが、(GIL には注意してください) 多くのワーカーを実行したい場合があるため、それらをピクルしようとするとピクルで例外がスローされます。_getstate_問題の原因となるエントリを削除することでこれを回避でき_setstate_ ますが、プロセスと状態を別々に保つだけであれば、これはもはや問題ではありません。

チェックポイントを設定するには、チェックポイント ファイルを既知の場所に保存し、プログラムの開始時にこのファイルが存在するかどうかを確認し、存在しない場合はプロセスが開始されていないことを確認し、そうでない場合はそれを読み込んで実行します。ワーカー スレッドが処理しているキューを空にし、状態オブジェクトを保存して、実行中のタスクを定期的にチェックポイントするスレッドを作成し、チェックポイント後に再開する場合に使用する再開ロジックを再利用します。

安全にチェックポイントを設定するには、pickle の途中で終了して、プログラムがチェックポイント ファイルを破損しないようにする必要があります。これをする

  1. 一時的な場所にチェックポイントを作成し、書き込みを終了
  2. 最後のチェックポイントの名前をに変更checkpoint.old
  3. 新しいチェックポイントの名前をcheckpoint.pickle
  4. 削除するcheckpoint.old
  5. プログラムを起動しcheckpoint.old、チェックポイントはなく. プログラムが他の場所で停止した場合は、単に再読み込みできます。checkpoint.oldcheckpoint.oldcheckpoint.picklecheckpoint.pickle
于 2017-09-15T04:03:07.643 に答える
1

これはコメントであり、回答ではありません。

Python の関数、クラス、またはプログラムをいつでもチェックポイントして復元するための汎用メカニズムを構築するのは困難です。簡単な部分は、属性がすべて基本データ型または基本データ型のコレクションであるクラス インスタンスをチェックポイントして復元するメカニズムです。次に、get_stateメソッドがクラスの実行中のインスタンスの状態をパッケージ化し、メソッドがrestore_state(checkpointed_state)状態を復元できます。

しかし、プログラムの多くの部分は基本データ型のコレクションではありません。これらには以下が含まれます:

  • プログラムポインタ
  • メソッドと関数への参照
  • ファイル ハンドル、ネットワーク ソケットなどを開きます。
  • サブプロセスの実行

これらはすべて、状態全体を取得するのが難しく、状態を復元するのが難しいため、チェックポイントと復元が困難です。

したがって、実行時間の長い分析をチェックポイント/復元したい場合は、Docker コンテナーまたは Linux プロセスCRIUのチェックポイント/復元など、より高いレベルのメカニズムを使用することをお勧めします。これらは完全にチェックポイントを設定してすべての状態を復元するわけではありませんが、構築できる以上のことを行うことに注意してください。

于 2020-08-28T15:11:24.313 に答える