ayukat1016 / gan_sample

MIT License
78 stars 25 forks source link

Windows 10における実行時のエラー "BrokenPipeError: [Errno 32] Broken pipe" #9

Closed T-H-ash closed 1 year ago

T-H-ash commented 3 years ago

概要

素晴らしい本をありがとうございます。本書がLinux向けであることは承知していますが、一部の変更を加えた上でWindows 10 のローカルPCにて実行しようと試みたところ、解決できないエラーが発生しました(Google Colab上ではエラーなく動作しました)。Linux環境もPytorchも初学者で慣れず、見当違いな質問である可能性がありますが、アドバイスを頂けたら幸いです。

再現

環境

実行コード

chapter4/section4_3_ESRGAN.ipynb

↑ 超解像タスクに関心があるため、Chap4から実行しています。

コードの変更点

As is

# In[44]
for epoch in range(1, opt.n_epoch + 1):
    for batch_num, imgs in enumerate(train_dataloader):
        batches_done = (epoch - 1) * len(train_dataloader) + batch_num
        # 事前学習
        if batches_done <= opt.warmup_batches:
            esrgan.pre_train(imgs, batches_done, batch_num)
        # 本学習
        else:
            esrgan.train(imgs, batches_done, batch_num)
        # 高解像度の生成画像の保存
        if batches_done % opt.sample_interval == 0:
            for i, imgs in enumerate(test_dataloader):
                esrgan.save_image(imgs, batches_done)
        # 学習した重みの保存
        if batches_done % opt.checkpoint_interval == 0:
            esrgan.save_weight(batches_done)
# エラー文
---------------------------------------------------------------------------
BrokenPipeError                           Traceback (most recent call last)
<ipython-input-70-22b6867ec45e> in <module>
      1 for epoch in range(1, opt.n_epoch + 1):
----> 2     for batch_num, imgs in enumerate(train_dataloader):
      3         batches_done = (epoch - 1) * len(train_dataloader) + batch_num
      4         # 事前学習
      5         if batches_done <= opt.warmup_batches:

~\Anaconda3\envs\pytorch17\lib\site-packages\torch\utils\data\dataloader.py in __iter__(self)
    350             return self._iterator
    351         else:
--> 352             return self._get_iterator()
    353 
    354     @property

~\Anaconda3\envs\pytorch17\lib\site-packages\torch\utils\data\dataloader.py in _get_iterator(self)
    292             return _SingleProcessDataLoaderIter(self)
    293         else:
--> 294             return _MultiProcessingDataLoaderIter(self)
    295 
    296     @property

~\Anaconda3\envs\pytorch17\lib\site-packages\torch\utils\data\dataloader.py in __init__(self, loader)
    799             #     before it starts, and __del__ tries to join but will get:
    800             #     AssertionError: can only join a started process.
--> 801             w.start()
    802             self._index_queues.append(index_queue)
    803             self._workers.append(w)

~\Anaconda3\envs\pytorch17\lib\multiprocessing\process.py in start(self)
    103                'daemonic processes are not allowed to have children'
    104         _cleanup()
--> 105         self._popen = self._Popen(self)
    106         self._sentinel = self._popen.sentinel
    107         # Avoid a refcycle if the target function holds an indirect

~\Anaconda3\envs\pytorch17\lib\multiprocessing\context.py in _Popen(process_obj)
    221     @staticmethod
    222     def _Popen(process_obj):
--> 223         return _default_context.get_context().Process._Popen(process_obj)
    224 
    225 class DefaultContext(BaseContext):

~\Anaconda3\envs\pytorch17\lib\multiprocessing\context.py in _Popen(process_obj)
    320         def _Popen(process_obj):
    321             from .popen_spawn_win32 import Popen
--> 322             return Popen(process_obj)
    323 
    324     class SpawnContext(BaseContext):

~\Anaconda3\envs\pytorch17\lib\multiprocessing\popen_spawn_win32.py in __init__(self, process_obj)
     63             try:
     64                 reduction.dump(prep_data, to_child)
---> 65                 reduction.dump(process_obj, to_child)
     66             finally:
     67                 set_spawning_popen(None)

~\Anaconda3\envs\pytorch17\lib\multiprocessing\reduction.py in dump(obj, file, protocol)
     58 def dump(obj, file, protocol=None):
     59     '''Replacement for pickle.dump() using ForkingPickler.'''
---> 60     ForkingPickler(file, protocol).dump(obj)
     61 
     62 #

BrokenPipeError: [Errno 32] Broken pipe

↑ エラー文のPATH内にあるpytorch17は私が設定した仮想環境名です。

To be

コア数を減らすことなく、BrokenPipeError: [Errno 32] Broken pipeを出さずに学習を実行したい。

Note

長文の質問失礼しました。Pytorch初学者なので分からないことも多く、どんなアドバイスも歓迎します。どうぞよろしくお願い致します。

hampen2929 commented 3 years ago

ご連絡ありがとうございます。 4章の超解像を担当いたしました、もちまると申します。 基本的にwindowsでの動作はサポート外ではありますが、今回は対応させていただきます。

>上記リンク先(isuue)の議論によれば実行部分をif name == "main"で括ればよいとの指摘もありますが、問題部分のセル(In[44])を括っても相変わらずエラーが出て正しく動作しません。In[42]「データセット」からIn[44]「学習」までをまとめてmainで括っても動作しません。

一点お伺いしたいのですが、こちらで実行した際にも同様に

BrokenPipeError: [Errno 32] Broken pipe

のエラーが出たということでしょうか?

hampen2929 commented 3 years ago

こちらの記事が参考になるかもしれません。 https://qiita.com/fmfm_mdk/items/726aeacf8f6efe10009e

T-H-ash commented 3 years ago

返信が遅くなり申し訳ありません!ご対応ありがとうございます!

一点お伺いしたいのですが、こちらで実行した際にも同様に BrokenPipeError: [Errno 32] Broken pipe のエラーが出たということでしょうか?

その通りです。In[42]からIn[44]までのひとつのセルにまとめ、if name == "main":で括って実行したところ、まずはIn[43]の出力であるところの「ESRGAN modelのSummary」が表示され、のちにissue本文にあるようなエラー文(BrokenPipeError: [Errno 32] Broken pipe)が表示されました。

実行セルは以下のようでした ↓

# 実行セル
if  __name__ == "__main__":

    train_dataloader = DataLoader(
        ImageDataset(train_data_dir, hr_shape=hr_shape),
        batch_size=opt.batch_size,
        shuffle=True,
        num_workers=opt.n_cpu,
    )

    test_dataloader = DataLoader(
        TestImageDataset(test_data_dir),
        batch_size=1,
        shuffle=False,
        num_workers=opt.n_cpu,
    )

    # ESRGANを呼び出す
    esrgan = ESRGAN(opt)

    for epoch in range(1, opt.n_epoch + 1):
        for batch_num, imgs in enumerate(train_dataloader):
            batches_done = (epoch - 1) * len(train_dataloader) + batch_num
            # 事前学習
            if batches_done <= opt.warmup_batches:
                esrgan.pre_train(imgs, batches_done, batch_num)
            # 本学習
            else:
                esrgan.train(imgs, batches_done, batch_num)
            # 高解像度の生成画像の保存
            if batches_done % opt.sample_interval == 0:
                for i, imgs in enumerate(test_dataloader):
                    esrgan.save_image(imgs, batches_done)
            # 学習した重みの保存
            if batches_done % opt.checkpoint_interval == 0:
                esrgan.save_weight(batches_done)

リンク先を拝見しました。

DataLoaderのインスタンス化とDatasetクラスの定義を同じ.pyで行ってはいけない.

この部分が具体的な指摘でしょうか。In[42]をmainで括ることよりも、Datasetクラス(本プログラムではImageDatasetTestImageDataset)を別の.pyファイルにまとめて置くことが必要であるのかもしれません。試してみます。

hampen2929 commented 3 years ago

ぜひ試してみてください!