所以我正在使用joblib来并行化一些代码,并且我发现在jupyter笔记本中使用它时无法打印内容。
我尝试在ipython中使用相同的示例,并且效果很好。
这是一个在jupyter笔记本单元中编写的最小(非)工作示例
from joblib import Parallel, delayed
Parallel(n_jobs=8)(delayed(print)(i) for i in range(10))
所以我得到的输出为[None, None, None, None, None, None, None, None, None, None]
,但是什么也没打印。
实际上,在检查笔记本进程的日志时,我注意到打印在那里发生。我希望打印发生在笔记本中,而不是笔记本过程的日志中。
答案 0 :(得分:6)
我认为,这部分是由Parallel
产生子工以及Jupyter Notebook如何处理这些工的IO引起的。在不指定backend
值的情况下启动时,Parallel
将默认为loky
,它利用直接使用fork-exec模型创建子流程的池化策略。
如果您使用
从终端启动Notebook$ jupyter-notebook
常规stderr
和stdout
流似乎仍然连接到该终端,而笔记本会话将在新的浏览器窗口中启动。在笔记本中运行发布的代码段 会产生预期的输出,但是它似乎到达了stdout
并最终到达了终端(如 Note 中所提示>)。这进一步证实了这种行为是由loky
与笔记本之间的交互作用以及笔记本为子进程处理标准IO流的方式引起的怀疑。
这导致我转到github上的this discussion(在本贴子发布之日起过去两周内有效),笔记本的作者似乎已经意识到了这一点,但是似乎没有明显且快速的解决方案解决目前的问题。
如果您不介意切换Parallel
用来生成子代的后端,则可以这样做:
from joblib import Parallel, delayed
Parallel(n_jobs=8, backend='multiprocessing')(delayed(print)(i) for i in range(10))
通过multiprocessing
后端,一切正常。 threading
看起来也很好。这可能不是您想要的解决方案,但希望在笔记本作者努力寻找合适的解决方案时就足够了。
我将把它交叉发布到GitHub上,以防万一有人想添加到这个答案中(我不想误解任何人的意图或在人们的嘴里说出来!)。
测试环境:
MacOS-Mojave(10.14)
Python-3.7.3
pip3-19.3.1
在2种配置中测试。确认同时为multiprocessing
使用threading
和backend
时产生预期的输出。软件包使用pip3
安装。
设置1:
ipykernel 5.1.1
ipython 7.5.0
jupyter 1.0.0
jupyter-client 5.2.4
jupyter-console 6.0.0
jupyter-core 4.4.0
notebook 5.7.8
设置2:
ipykernel 5.1.4
ipython 7.12.0
jupyter 1.0.0
jupyter-client 5.3.4
jupyter-console 6.1.0
jupyter-core 4.6.2
notebook 6.0.3
我也成功使用了与“设置2”相同的版本,但是将notebook
软件包的版本降级为6.0.2.。
此方法在Windows上不一致。软件版本的不同组合会产生不同的结果。做最直观的事情-将所有内容升级到最新版本-不能保证它会起作用。
答案 1 :(得分:0)
在 Z4 层的 git link scottgigante 的方法在 Windows 中工作,但与提到的结果相反:在 Jupyter notebook 中,“多处理”后端永远挂起,但默认的 loky 运行良好(python 3.8.5 和 notebook 6.1.1 ):
from joblib import Parallel, delayed
import sys
def g(x):
stream = getattr(sys, "stdout")
print("{}".format(x), file=stream)
stream.flush()
return x
Parallel(n_jobs=2)(delayed(g)(x**2) for x in range(5))
executed in 91ms, finished 11:17:25 2021-05-13
[0, 1, 4, 9, 16]
更简单的方法是延迟使用恒等函数:
Parallel(n_jobs=2)(delayed(lambda y:y)([np.log(x),np.sin(x)]) for x in range(5))
executed in 151ms, finished 09:34:18 2021-05-17
[[-inf, 0.0],
[0.0, 0.8414709848078965],
[0.6931471805599453, 0.9092974268256817],
[1.0986122886681098, 0.1411200080598672],
[1.3862943611198906, -0.7568024953079282]]
或者像这样使用:
Parallel(n_jobs=2)(delayed(lambda y:[np.log(y),np.sin(y)])(x) for x in range(5))
executed in 589ms, finished 09:44:57 2021-05-17
[[-inf, 0.0],
[0.0, 0.8414709848078965],
[0.6931471805599453, 0.9092974268256817],
[1.0986122886681098, 0.1411200080598672],
[1.3862943611198906, -0.7568024953079282]]