data = self._data_queue.get(timeout=timeout)RuntimeError: DataLoader worker (pid(s) 8528, 8488) exit

文章目录

  • 报错输出
  • 出错原因
  • 解决方法

报错输出

我在Windows环境下,运行Yolov5的代码时,代码中多线程取出数据出现了以下的错误:

RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
Traceback (most recent call last):
  File "D:\Software\Anaconda\envs\pytorch\lib\site-packages\torch\utils\data\dataloader.py", line 761, in _try_get_data
    data = self._data_queue.get(timeout=timeout)
  File "D:\Software\Anaconda\envs\pytorch\lib\multiprocessing\queues.py", line 105, in get
    raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/WorkSpace/Codes/Pycharm/2020/NPyTorch/Minibatchtraing.py", line 24, in <module>
    for step, (batch_x, batch_y) in enumerate(loader):
  File "D:\Software\Anaconda\envs\pytorch\lib\site-packages\torch\utils\data\dataloader.py", line 345, in __next__
    data = self._next_data()
  File "D:\Software\Anaconda\envs\pytorch\lib\site-packages\torch\utils\data\dataloader.py", line 841, in _next_data
    idx, data = self._get_data()
  File "D:\Software\Anaconda\envs\pytorch\lib\site-packages\torch\utils\data\dataloader.py", line 808, in _get_data
    success, data = self._try_get_data()
  File "D:\Software\Anaconda\envs\pytorch\lib\site-packages\torch\utils\data\dataloader.py", line 774, in _try_get_data
    raise RuntimeError('DataLoader worker (pid(s) {}) exited unexpectedly'.format(pids_str))
RuntimeError: DataLoader worker (pid(s) 8528, 8488) exited unexpectedly

可以发现,上面的DataLoader有两个PID 8528, 8488,表示其有两个进程,而两个进程报错,则说明多进程的设置有问题。

出错原因

上述错误的提示含义为:您试图在当前进程完成引导阶段之前启动新进程。这可能意味着您没有使用fork来启动子进程,并且忘记了在主模块中使用适当的习语。还有一种情况是,如果您的程序不会被冻结为生成Windows可执行文件,则可以省略 “freeze_support()” 行。

其实真正原因的出现还是Windows操作系统与Linux操作系统的差异。

在Linux操作系统中,其提供了一个fork()系统调用,用于创建子进程,有了fork调用,一个进程在接到新任务时就可以复制出一个子进程来处理新 任务,常见的Apache服务器就是由父进程监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。

但是,Windows中是并没有fork()系统调用的,是使用的 spawn 命令,那该怎么办呢?

multiprocessing模块本来就是跨平台版本的多进程模块,其设计的时候就考虑到了Linux和Windows操作系统的差异,但因为Windows缺乏linix那种fork, 所以它会有一些额外的限制:

  • 不管是绑定还是未绑定的方法, 都不要直接作为参数传给Process初始化的target, 相反应该要用普通的函数代替
  • 子进程在访问全局变量时, 可能会与父进程的值不同 ( 模块级别的常量没这问题 )
  • 开启新Python解析器或者创建新process时, 确定主模块能够安全的导入.

这也就解释了为什么Windows下使用多进程模块 multiprocessing 必须要有主函数存在了,因为 spawn命令需要区分主进程,上述的报错其实就是忽略了第三点的要求。

解决方法

要解决上面的错误也很简单,在主函数 if __name__ == '__main__': 的第一行加上 multiprocessing.freeze_support() ,使得主进程能够得到区分,这里我是运行Yolov5的代码出错的,我就用其主函数来演示,其修改如下:

import multiprocessing


"""
其他代码
"""

if __name__ == "__main__":
    multiprocessing.freeze_support()
    opt = parse_opt()
    main(opt)

你可能感兴趣的:(Error,python,pytorch)