无法转换为多处理 python 代码到 cython
Trouble transitioning to multiprocessing python code to cython
我正在 运行ning 一个程序,它在 Raspberry pi 4 上获取实时数据。因为这个程序要求很高,所以不同的功能被分离到不同的内核中,使用池进行多处理,每个进程都是一个 MQTT 客户端。
我一直在尝试将代码转换为 Cython,但我 运行 遇到了多处理问题。从网上看到的帖子来看,使用的是prange。但是当试图将 mqtt 客户端传递给 prange 时,我得到了关于 nogil 的错误。有没有办法将 Pool 与 Cython 一起使用,或者使用需要 gil 的多个进程与 Cython 并行 运行?
抱歉,这听起来像是一个新手问题,我也很抱歉,但我无法显示代码。
在此先感谢您的帮助。
编辑:
目前我停留在 Pool 的地图部分。这是其中的一段代码:
def clie1(num):
global id1
print("Clie1")
mqttBroker="mqtt.eclipseprojects.io"
id1 = os.getpid()
client.on_connect = on_connect
client.on_message = on_message
client.connect(mqttBroker, 1883, 60)
#client.connect("127.0.0.1", 1883, 60)
client.loop_forever()
def clie2(num):
global id2
print("Clie2")
mqttBroker="mqtt.eclipseprojects.io"
id2 = os.getpid()
client2.on_connect = on_connect2
client2.on_message = on_message2
client2.connect(mqttBroker, 1883, 60)
#client2.connect("127.0.0.1", 1883, 60)
client2.loop_forever()
def smap(f):
return f()
client = mqtt.Client()
client2 = mqtt.Client()
def main():
fc1 = functools.partial(clie1, 1)
fc2 = functools.partial(clie2, 2)
print("Pool")
with Pool() as pool:
res = pool.map(smap, [fc1,fc2])
main()
最终结果:
我的安装文件非常简单,可能需要一些额外的东西才能工作:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("MyFile.pyx"),
)
所以我们确定的问题是:对于 运行 它是您需要的 .py 文件
if __name__=="__main__":
main()
然而,Cython 文件不能 运行“作为脚本”,因此 __name__
永远不会 "__main__"
。 (原则上这适用于 embedded Cython,但我认为这对你没有帮助)。
解决方案是编写一个微型 Python 脚本来导入您的 Cython 模块并调用其 main()
函数:
# Do NOT compile this script with Cython!
import my_cython_mod
if __name__ == "__main__":
my_cython_mod.main()
当你这样做时,你的示例的 cut-down 版本 运行 对我来说很好。
我正在 运行ning 一个程序,它在 Raspberry pi 4 上获取实时数据。因为这个程序要求很高,所以不同的功能被分离到不同的内核中,使用池进行多处理,每个进程都是一个 MQTT 客户端。
我一直在尝试将代码转换为 Cython,但我 运行 遇到了多处理问题。从网上看到的帖子来看,使用的是prange。但是当试图将 mqtt 客户端传递给 prange 时,我得到了关于 nogil 的错误。有没有办法将 Pool 与 Cython 一起使用,或者使用需要 gil 的多个进程与 Cython 并行 运行?
抱歉,这听起来像是一个新手问题,我也很抱歉,但我无法显示代码。
在此先感谢您的帮助。
编辑: 目前我停留在 Pool 的地图部分。这是其中的一段代码:
def clie1(num):
global id1
print("Clie1")
mqttBroker="mqtt.eclipseprojects.io"
id1 = os.getpid()
client.on_connect = on_connect
client.on_message = on_message
client.connect(mqttBroker, 1883, 60)
#client.connect("127.0.0.1", 1883, 60)
client.loop_forever()
def clie2(num):
global id2
print("Clie2")
mqttBroker="mqtt.eclipseprojects.io"
id2 = os.getpid()
client2.on_connect = on_connect2
client2.on_message = on_message2
client2.connect(mqttBroker, 1883, 60)
#client2.connect("127.0.0.1", 1883, 60)
client2.loop_forever()
def smap(f):
return f()
client = mqtt.Client()
client2 = mqtt.Client()
def main():
fc1 = functools.partial(clie1, 1)
fc2 = functools.partial(clie2, 2)
print("Pool")
with Pool() as pool:
res = pool.map(smap, [fc1,fc2])
main()
最终结果:
我的安装文件非常简单,可能需要一些额外的东西才能工作:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("MyFile.pyx"),
)
所以我们确定的问题是:对于 运行 它是您需要的 .py 文件
if __name__=="__main__":
main()
然而,Cython 文件不能 运行“作为脚本”,因此 __name__
永远不会 "__main__"
。 (原则上这适用于 embedded Cython,但我认为这对你没有帮助)。
解决方案是编写一个微型 Python 脚本来导入您的 Cython 模块并调用其 main()
函数:
# Do NOT compile this script with Cython!
import my_cython_mod
if __name__ == "__main__":
my_cython_mod.main()
当你这样做时,你的示例的 cut-down 版本 运行 对我来说很好。