On Windows machines everything in your script must be inside of an if __name__ == ‘__main__‘: block

问题

On Windows machines everything in your script must be inside of an if __name__ == '__main__': block in order for multiprocess to work.

On Windows machines everything in your script must be inside of an if name == ‘main’: block in order for multiprocess to work.
在 Windows 机器上,脚本中的所有内容都必须位于 if _ _ name _ _ = =’_ _ main _ _’: 块中,这样多进程才能工作。

文档解释

在 Windows 上的 python 中使用多处理时,需要保护程序的入口点。文档说: “确保新的 Python 解释器可以安全地导入主模块,而不会造成意想不到的副作用(比如启动新进程)(Make sure that the main module can be safely imported by a new Python interpreter without causing unintended side effects (such a starting a new process))”。

问题解释

The multiprocessing module works by creating new Python processes that will import your module. If you did not add name== ‘main’ protection then you would enter a never ending loop of new process creation. It goes like this:

多处理模块通过创建新的 Python 进程来工作,这些进程将导入您的模块。如果您没有添加 _ _ name _ _ = =’_ _ main _ _’保护,那么您将进入一个永无止境的创建新进程的循环。它是这样的:

Your module is imported and executes code during the import that cause multiprocessing to spawn 4 new processes.
导入模块并在导入期间执行代码,这会导致多处理产生4个新进程。

Those 4 new processes in turn import the module and executes code during the import that cause multiprocessing to spawn 16 new processes.
这4个新进程依次导入模块,并在导入期间执行代码,从而导致多进程产生16个新进程。

Those 16 new processes in turn import the module and executes code during the import that cause multiprocessing to spawn 64 new processes.
这16个新进程依次导入模块,并在导入期间执行代码,从而导致多进程产生64个新进程。

So the idea is that you make sure that the process spawning only happens once. And that is achieved most easily with the idiom of the name== ‘main’ protection.
所以我们的想法是确保进程只产生一次。使用“ _ _ name _ _ = =’_ _ main _ _’保护”这个习惯用语可以最容易地实现这一点。

解决办法

在 Windows 机器上运行multiprocess时,将脚本中的所有内容放在 if _ _ name _ _ = =’_ _ main _ _’: 块中运行,这样多进程才能工作。

if __name__ == '__main__':
    from multiprocessing import freeze_support
    import uncertainpy as un
    import chaospy as cp
    from multiprocessing import Process, freeze_support
    from valderrama import valderrama
    freeze_support()
    # Initialize the model
    model = un.Model(run=valderrama,
                    labels=["Time (ms)", "Membrane potential (mV)"])

    # Define a parameter list
    parameters = {"V_0": -10,
                "C_m": 1,
                "gbar_Na": 120,
                "gbar_K": 36,
                "gbar_L": 0.3,
                "m_0": 0.0011,
                "n_0": 0.0003,
                "h_0": 0.9998,
                "E_Na": 112,
                "E_K": -12,
                "E_l": 10.613}

    # Create the parameters
    parameters = un.Parameters(parameters)

    # Set all parameters to have a uniform distribution
    # within a 20% interval around their fixed value
    parameters.set_all_distributions(un.uniform(0.2))
    
    # Perform the uncertainty quantification
    UQ = un.UncertaintyQuantification(model,
                                    parameters=parameters)
    # We set the seed to easier be able to reproduce the result
    data = UQ.quantify(seed=10)

拓展

Expanding a bit on the good answer you already got, it helps if you understand what Linux-y systems do. They spawn new processes using fork(), which has two good consequences:

如果您了解 Linux-y 系统的功能,那么对您已经得到的好答案进行一点扩展将会有所帮助。它们使用 fork ()产生新的进程,这有两个好的结果:

All data structures existing in the main program are visible to the child processes. They actually work on copies of the data.
主程序中存在的所有数据结构对于子进程都是可见的。他们实际上是在处理数据的副本。

The child processes start executing at the instruction immediately following the fork() in the main program - so any module-level code already executed in the module will not be executed again.
子进程在主程序的 fork ()之后的指令处立即开始执行-因此在模块中已经执行的任何模块级代码都不会再次执行。

fork() isn’t possible in Windows, so on Windows each module is imported anew by each child process. So:

fork ()在 Windows 中是不可能的,所以在 Windows 中每个子进程都会重新导入每个模块。因此:

On Windows, no data structures existing in the main program are visible to the child processes; and,
在 Windows 上,主程序中现有的数据结构对子进程不可见;

All module-level code is executed in each child process.
所有模块级代码都在每个子进程中执行。

So you need to think a bit about which code you want executed only in the main program. The most obvious example is that you want code that creates child processes to run only in the main program - so that should be protected by name == ‘main’. For a subtler example, consider code that builds a gigantic list, which you intend to pass out to worker processes to crawl over. You probably want to protect that too, because there’s no point in this case to make each worker process waste RAM and time building their own useless copies of the gigantic list.

因此,您需要考虑一下只希望在主程序中执行哪些代码。最明显的例子是,您希望创建子进程的代码仅在主程序中运行——因此应该由 _ _ name _ _ = =’_ _ main _ _’保护。对于一个更微妙的示例,考虑构建一个巨大列表的代码,您打算将这个列表传递给工作进程以进行爬行。您可能也想保护它,因为在这种情况下没有必要让每个工作进程浪费 RAM 和时间构建它们自己的巨大列表的无用副本。

Note that it’s a Good Idea to use name == “main” appropriately even on Linux-y systems, because it makes the intended division of work clearer. Parallel programs can be confusing - every little bit helps;
请注意,即使在 Linux-y 系统上适当地使用 _ _ name _ _ = = “ _ _ main _ _”也是一个好主意,因为它使预期的工作分工更加清晰。并行程序可能会让人感到困惑——每一点都有帮助.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值