pytorch はモデルの実行時間、GPU 時間、CPU 時間を測定します。model.eval() の概要

1. 時間の計測方法

time.time()
time.perf_counter()
time.process_time()

time.time() と time.perf_counter() には sleep() 時間が含まれており、一般的な時間測定として使用できます。 time.perf_counter() の方がより正確で、 time.process_time() は
システムとユーザーの CPU 時間の合計です。現在のプロセス

テストコード:

def show_time():
    print('我是time()方法:{}'.format(time.time()))
    print('我是perf_counter()方法:{}'.format(time.perf_counter()))
    print('我是process_time()方法:{}'.format(time.process_time()))
    t0 = time.time()
    c0 = time.perf_counter()
    p0 = time.process_time()
    r = 0
    for i in range(10000000):
        r += i
    time.sleep(2)
    print(r)
    t1 = time.time()
    c1 = time.perf_counter()
    p1 = time.process_time()
    spend1 = t1 - t0
    spend2 = c1 - c0
    spend3 = p1 - p0
    print("time()方法用时:{}s".format(spend1))
    print("perf_counter()用时:{}s".format(spend2))
    print("process_time()用时:{}s".format(spend3))
    print("测试完毕")

テスト結果:
ここに画像の説明を挿入
より詳しい説明は、
Python3.7 の time モジュールの time()、perf_counter()、process_time() の違いを参照してください。

2. Model.eval()、model.train()、torch.no_grad()メソッドの紹介

2.1model.train()とmodel.eval()

pytorch では、モデルに設定できる 2 つのモードがあることがわかっています。1 つは train モード、もう 1 つは eval モードです。

model.train() の役割は、バッチ正規化とドロップアウトを有効にすることです。トレイン モードでは、ドロップアウト層は、設定されたパラメーター p (keep_prob=0.8 など) に従ってアクティベーション ユニットを保持する確率を設定し、バッチ正規化層はデータの平均と変数の計算と更新を継続します。

model.eval() の機能は、バッチ正規化とドロップアウトを有効にすることではありません。eval モードでは、ドロップアウト層はすべてのアクティベーション ユニットを渡しますが、バッチ正規化層は平均値と変数の計算と更新を停止し、トレーニング フェーズ中に学習された平均値と変数値を直接使用します。

model.eval() を使用する場合、モデルをテストモードに切り替えるため、トレーニングモードのように重みを更新しません。ただし、model.eval() は各層の勾配計算の動作には影響しないことに注意してください。つまり、勾配計算と保存はトレーニング モードと同じ方法で実行されますが、逆伝播は実行されません。

2.2 model.eval() と torch.no_grad()

model.eval() について話すとき、実際には torch.no_grad() について言及されます。

torch.no_grad() は autograd の計算を停止するために使用されます。これにより、ビデオ メモリが高速化され、節約されますが、ドロップアウト レイヤーとバッチ正規化レイヤーの動作には影響しません。

メモリ サイズと計算時間を気にしない場合は、model.eval() を使用するだけで正しい検証結果が得られますが、torch.zero_grad() を使用すると、GPU スペースをさらに高速化して節約できます。勾配を計算して保存する必要がないため、勾配をより速く計算し、より大きなバッチを使用してモデルを実行できます。

3. モデル推論時間モード

時間を計測する場合、以下のコードが間違っているなど、一般的なテストとは異なります。

start = time.time()
result = model(input)
end = time.time()

代わりに、以下を使用します。

torch.cuda.synchronize()
start = time.time()
result = model(input)
torch.cuda.synchronize()
end = time.time()

pytorch ではプログラムの実行が非同期であるためです。
コード 1 を使用した場合、プログラムは end=time.time() の実行後に終了し、Python の終了によりバックグラウンドの cu も終了するため、テスト時間は非常に短くなります。
コード 2 が使用される場合、コードは cu の操作を同期し、GPU での操作が完了するのを待ってから、end = time.time() の整形を続行します。

4. モデル推論時間をテストするための完全なコード

一般に、最初に model.eval() はバッチ正規化とドロップアウトを有効にせず、勾配更新を有効にせず、
次に mode を使用してモデルを作成し、入力データ (単一イメージ) を初期化します。

def measure_inference_speed(model, data, max_iter=200, log_interval=50):
    model.eval()

    # the first several iterations may be very slow so skip them
    num_warmup = 5
    pure_inf_time = 0
    fps = 0

    # benchmark with 2000 image and take the average
    for i in range(max_iter):

        torch.cuda.synchronize()
        start_time = time.perf_counter()

        with torch.no_grad():
            model(*data)

        torch.cuda.synchronize()
        elapsed = time.perf_counter() - start_time

        if i >= num_warmup:
            pure_inf_time += elapsed
            if (i + 1) % log_interval == 0:
                fps = (i + 1 - num_warmup) / pure_inf_time
                print(
                    f'Done image [{
      
      i + 1:<3}/ {
      
      max_iter}], '
                    f'fps: {
      
      fps:.1f} img / s, '
                    f'times per image: {
      
      1000 / fps:.1f} ms / img',
                    flush=True)

        if (i + 1) == max_iter:
            fps = (i + 1 - num_warmup) / pure_inf_time
            print(
                f'Overall fps: {
      
      fps:.1f} img / s, '
                f'times per image: {
      
      1000 / fps:.1f} ms / img',
                flush=True)
            break
    return fps
if __name__ == "__main__":
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    # device = 'cpu'
    print(device)
    img_channel = 3
    width = 32

    enc_blks = [2, 2, 4, 8]
    middle_blk_num = 12
    dec_blks = [2, 2, 2, 2]

    width = 16
    enc_blks = [1, 1, 1]
    middle_blk_num = 1
    dec_blks = [1, 1, 1]

    net = NAFNet(img_channel=img_channel, width=width, middle_blk_num=middle_blk_num,
                 enc_blk_nums=enc_blks, dec_blk_nums=dec_blks)
    net = net.to(device)

    data = [torch.rand(1, 3, 256, 256).to(device)]
    fps = measure_inference_speed(net, data)
    print('fps:', fps)

ここに画像の説明を挿入

5. 参考:

https://blog.csdn.net/weixin_44317740/article/details/104651434
https://zhuanlan.zhihu.com/p/547033884
https://dec.ai/blog/measure-inference-time-deep-neural-ネットワーク/
https://github.com/xinntao/BasicSR

おすすめ

転載: blog.csdn.net/tywwwww/article/details/130684141