Dask with cython in Juypter: ModuleNotFoundError: No module named '_cython_magic
Dask with cython in Juypter: ModuleNotFoundError: No module named '_cython_magic
我得到:
KilledWorker: ("('from_pandas-1445321946b8a22fc0ada720fb002544', 4)", 'tcp://127.0.0.1:45940')
我已经阅读了关于后一条错误消息的 ,但这一切都与堆栈跟踪顶部的错误消息一起出现令人困惑:
distributed.utils - ERROR - Worker already exists tcp://127.0.0.1:35780
我笔记本的 Jupyter notebook
命令通过管道传输到终端 运行 的实际错误:
ModuleNotFoundError: No module named '_cython_magic_faba6120a194ab58ae9efd1da474433f'
既然我在我的案例中找到了详细的错误,那么我将研究如何自己解决这个问题。关于这种特殊配置的精确提示会很好,但我想将所有 cython 代码提取到 notebook 之外的 python 代码更明智,而不是敲打 dask 了解 cython 魔法命令?
具体的 cython 错误看起来确实来自将编译配置为对工作人员可见的问题。当您执行 %%cython
时,会创建并构建一个临时扩展,最终导入到本地(客户端)会话中,而无需安装到 python 环境中。我不确定这到底是怎么发生的。
你至少应该确保在编译你的 cython 单元之后创建你的客户端,然后它们可能会继承所需的环境,但是猴子很有可能用细胞魔法修补太复杂了,无论如何都行不通。
这是一个完整的玩具示例(使用 SLURM 集群在 JupyterLab 上测试)。
该示例使用 Cython 编译了一个对两个整数求和的简单函数,但当然可以将相同的技术应用于复杂(且更有用)的代码。
这里的关键技巧是必须设置 Workers 来查找和导入 Cython 库。
这需要导入pyximport
,调用pyximport.install()
,然后在每个Worker上导入Cython-generated模块。这是使用 register_worker_callback()
完成的。
注意Cython-generated模块放在<IPYTHONCACHEDIR/cython
目录下(IPYTHONCACHEDIR
可以通过调用IPython.paths.get_ipython_cache_dir()
找到)。该目录必须添加到 Python 查找模块的路径中,以便可以加载 Cython-generated 模块。
此示例假定 SLURM,但这只是为了我的方便。
dask.distributed "network" 可以用任何其他方法设置(例如参见 [=17=])。
from dask import delayed
%load_ext cython
# Create a toy Cython function and put it into a module named remoteCython
%%cython -n remoteCython
def cython_sum(int a, int b):
return a+b
# Set up a distributed cluster (minimal, just for illustration)
# I use SLURM.
from dask_jobqueue import SLURMCluster
from distributed import Client
cluster = SLURMCluster(memory="1GB",
processes=1,
cores=1,
walltime="00:10:00")
cluster.start_workers(1) # Start as many workers as needed.
client = Client(cluster)
def init_pyx(dask_worker):
import pyximport
pyximport.install()
import sys
sys.path.insert(0,'<IPYTHONCACHEDIR>/cython/') # <<< replace <IPYTHONCACHEDIR> as appropriate
import remoteCython
client.register_worker_callbacks(init_pyx) # This runs init_pyx() on any Worker at init
import remoteCython
# ASIDE: you can find where the full path of Cython-generated library by
# looking at remoteCython.__file__
# The following creates a task and submits to the scheduler.
# The task computes the sum of 123 and 321 via the Cython function defined above
future = client.compute(delayed(remoteCython.cython_sum)(123,321))
# The task is executed on the remote worker
# We fetch the result from the remote worker
print(future.result()) # This prints 444
# We're done. Let's release the SLURM jobs.
cluster.close()
我得到:
KilledWorker: ("('from_pandas-1445321946b8a22fc0ada720fb002544', 4)", 'tcp://127.0.0.1:45940')
我已经阅读了关于后一条错误消息的
distributed.utils - ERROR - Worker already exists tcp://127.0.0.1:35780
我笔记本的 Jupyter notebook
命令通过管道传输到终端 运行 的实际错误:
ModuleNotFoundError: No module named '_cython_magic_faba6120a194ab58ae9efd1da474433f'
既然我在我的案例中找到了详细的错误,那么我将研究如何自己解决这个问题。关于这种特殊配置的精确提示会很好,但我想将所有 cython 代码提取到 notebook 之外的 python 代码更明智,而不是敲打 dask 了解 cython 魔法命令?
具体的 cython 错误看起来确实来自将编译配置为对工作人员可见的问题。当您执行 %%cython
时,会创建并构建一个临时扩展,最终导入到本地(客户端)会话中,而无需安装到 python 环境中。我不确定这到底是怎么发生的。
你至少应该确保在编译你的 cython 单元之后创建你的客户端,然后它们可能会继承所需的环境,但是猴子很有可能用细胞魔法修补太复杂了,无论如何都行不通。
这是一个完整的玩具示例(使用 SLURM 集群在 JupyterLab 上测试)。
该示例使用 Cython 编译了一个对两个整数求和的简单函数,但当然可以将相同的技术应用于复杂(且更有用)的代码。
这里的关键技巧是必须设置 Workers 来查找和导入 Cython 库。
这需要导入pyximport
,调用pyximport.install()
,然后在每个Worker上导入Cython-generated模块。这是使用 register_worker_callback()
完成的。
注意Cython-generated模块放在<IPYTHONCACHEDIR/cython
目录下(IPYTHONCACHEDIR
可以通过调用IPython.paths.get_ipython_cache_dir()
找到)。该目录必须添加到 Python 查找模块的路径中,以便可以加载 Cython-generated 模块。
此示例假定 SLURM,但这只是为了我的方便。
dask.distributed "network" 可以用任何其他方法设置(例如参见 [=17=])。
from dask import delayed
%load_ext cython
# Create a toy Cython function and put it into a module named remoteCython
%%cython -n remoteCython
def cython_sum(int a, int b):
return a+b
# Set up a distributed cluster (minimal, just for illustration)
# I use SLURM.
from dask_jobqueue import SLURMCluster
from distributed import Client
cluster = SLURMCluster(memory="1GB",
processes=1,
cores=1,
walltime="00:10:00")
cluster.start_workers(1) # Start as many workers as needed.
client = Client(cluster)
def init_pyx(dask_worker):
import pyximport
pyximport.install()
import sys
sys.path.insert(0,'<IPYTHONCACHEDIR>/cython/') # <<< replace <IPYTHONCACHEDIR> as appropriate
import remoteCython
client.register_worker_callbacks(init_pyx) # This runs init_pyx() on any Worker at init
import remoteCython
# ASIDE: you can find where the full path of Cython-generated library by
# looking at remoteCython.__file__
# The following creates a task and submits to the scheduler.
# The task computes the sum of 123 and 321 via the Cython function defined above
future = client.compute(delayed(remoteCython.cython_sum)(123,321))
# The task is executed on the remote worker
# We fetch the result from the remote worker
print(future.result()) # This prints 444
# We're done. Let's release the SLURM jobs.
cluster.close()