在Python3中同时搜索图形

在Python3中同时搜索图形,python,multithreading,graph,multiprocessing,python-3.3,Python,Multithreading,Graph,Multiprocessing,Python 3.3,我想创建一个小型p2p应用程序,它可以并发处理来自其他已知/受信任节点的传入数据(它主要存储在SQLite数据库中)。为了识别这些节点,在连接时,每个节点都会介绍自己,然后我的应用程序需要检查它是否直接或可能通过另一个节点间接地了解这个节点。因此,我需要进行图形搜索,这显然需要处理时间,并且我希望将其外包给一个单独的流程(甚至多个工作流程?请参见下面的第二个问题)。此外,在某些情况下,有必要调整图形,添加新边或顶点 假设我有4个工作进程通过异步I/O接受和处理传入的连接。它们访问(读取/修改)图

我想创建一个小型p2p应用程序,它可以并发处理来自其他已知/受信任节点的传入数据(它主要存储在SQLite数据库中)。为了识别这些节点,在连接时,每个节点都会介绍自己,然后我的应用程序需要检查它是否直接或可能通过另一个节点间接地了解这个节点。因此,我需要进行图形搜索,这显然需要处理时间,并且我希望将其外包给一个单独的流程(甚至多个工作流程?请参见下面的第二个问题)。此外,在某些情况下,有必要调整图形,添加新边或顶点

假设我有4个工作进程通过异步I/O接受和处理传入的连接。它们访问(读取/修改)图形的最佳方式是什么?单个队列显然无法实现读取访问,因为我需要以某种方式将搜索结果传回

因此,一种方法是另一个队列,该队列将由图形搜索过程填充,我可以将其添加到事件循环中。然后,事件循环可以将结果传递给处理程序。但是,这种基于事件/回调的方法还需要始终将相应的套接字传递给回调,从而传递给队列,这是因为套接字是不可拾取的。(更不用说回调会导致意大利面代码了。)

我刚刚想到的另一个想法可能是为每个传入连接创建一个到图形进程的管道,然后在图形方面也执行异步I/O。然而,为了避免回调,如果我理解正确的话,我需要一个异步I/O库,利用来自的
收益(即)。还有其他选择吗


关于图形侧的异步I/O:这当然是一次处理许多传入请求的最佳方法,但执行图形查找是一项CPU密集型任务,因此可以从使用多个工作线程或进程中获益问题在于:多线程允许共享数据,但Python的GIL在某种程度上否定了性能优势。另一方面,多个进程没有这个问题,但如何在它们之间共享和同步数据?(对我来说,拆分一个图表似乎是不可能的。)有什么办法可以很好地解决这个问题吗?另外,在性能方面,将异步I/O与多线程/多处理相结合是否有意义?

回答您的最后一个问题:是的!但是,我想,问题是:混合事件和线程有意义吗?您可以查看这篇关于混合并发模型的文章:

我的建议:从一个进程和一个事件循环开始,就像郁金香模型一样。我将尝试解释如何使用tulip使事件+异步I/O(以及线程或其他进程)完全没有回调

您可以使用类似于
accept=yield from check\u incoming()
,这应该是一个郁金香协同程序(check\u incoming),在这个函数中,您可以使用
loop.run\u in\u executor()
在线程/进程池中运行图形搜索(稍后我将对此进行详细解释)。此函数
run\u in\u executor()
返回一个未来,您也可以
从任务中退出。wait([Future\u returned\u by\u run\u in\u executor],loop=self)
。下一步是执行器.result()中的运行返回的
result=future\u,最后返回
True
False

进程池要求只能执行和返回可拾取的对象。这个要求不是问题,但它隐含着图形操作必须在函数中自包含,并且必须以某种方式获得图形实例。线程池存在GIL问题,因为您提到了CPU受限的任务,这可能会导致“获取GIL冲突”,但在新的Python3.xGIL中这一点得到了改进。两种解决方案都有局限性

所以。。您可以使用另一个具有自己的事件循环的单个进程,而不是池来管理所有图形工作,并使用unix域套接字连接这两个进程

第二个进程与第一个进程一样,也必须接受传入连接(但现在它们来自已知的源),并且可以使用线程池,就像我前面所说的那样,但它不会与第一个事件循环进程(处理外部客户机的进程)发生“冲突”,只会与第二个事件循环发生冲突。共享同一图形实例的线程需要一些锁定/解锁


希望有帮助

谢谢你这么长时间后的回复!我不确定我是否理解了您编写的所有内容:您是否建议让一个进程/事件循环处理传入的外部请求,另一个进行实际搜索,可能是通过提供一个工作线程池(这需要线程安全编程)?在任何情况下,我仍然不相信图形搜索的性能实际上会从使用线程中获益。最后,你能详细说明一下你在第3段中写的东西吗?我有点困惑:
check\u incoming()
到底应该做什么?我希望它只会产生一个新的传入(内部)搜索请求。还有,我如何从任务中
让步。等待([future\u returned\u by\u run\u in\u executor],loop=self)
run\u in\u executor()返回的未来?你能举个代码示例吗?嗨!关于第一条评论:是的,2个进程,每个进程都有自己的事件循环。。我提到了线程池,但我不会使用它。。如果任务受cpu限制,线程就不会真正受益。。但即使如此,这在Python3上也比在Python2上好。关于第二条评论:check_incoming将处理侦听套接字上的读取事件。只需接受()一个连接并检查是否要关闭或保留它,然后返回客户机本身(文件描述符或某个高级对象)或无。。最后