Python评测:“select.poll”对象的“poll”方法是什么?

Python评测:“select.poll”对象的“poll”方法是什么?,python,methods,profiling,Python,Methods,Profiling,我使用python的cProfile模块分析了我的python代码,得到了以下结果: ncalls tottime percall cumtime percall filename:lineno(function) 13937860 96351.331 0.007 96351.331 0.007 {method 'poll' of 'select.poll' objects} 13930480 201.012 0.000 201.012 0.000

我使用python的cProfile模块分析了我的python代码,得到了以下结果:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 13937860 96351.331    0.007 96351.331    0.007 {method 'poll' of 'select.poll' objects}
 13930480  201.012    0.000  201.012    0.000 {built-in method posix.read}
 13937860  180.207    0.000 97129.916    0.007 connection.py:897(wait)
 13937860  118.066    0.000 96493.283    0.007 selectors.py:356(select)
  6968925   86.243    0.000 97360.129    0.014 queues.py:91(get)
 13937860   76.067    0.000  194.402    0.000 selectors.py:224(register)
 13937860   64.667    0.000 97194.582    0.007 connection.py:413(_poll)
 13930480   64.365    0.000  279.040    0.000 connection.py:374(_recv)
31163538/17167548   64.083    0.000  106.596    0.000 records.py:230(__getattribute__)
 13937860   57.454    0.000  264.845    0.000 selectors.py:341(register)
...
显然,我的程序大部分运行时间都花在“select.poll”对象的“poll”方法上。但是,我不知道什么时候调用这个方法以及为什么调用这个方法,也不知道为了减少这些方法调用,我必须在程序中更改什么

那么,我可以寻找什么来避免代码中的这个瓶颈呢


我在Linux服务器上使用64位python 3.5和numpy。

它是python库的一部分。它用于从I/O读取事件。根据定义,它将等待事件,因此需要更长的时间。不是你应该改变的东西。

在做了一些实验后,我发现:我的程序用sharedmem的并行映射方法完成了大部分工作:

with sharedmem.MapReduce() as pool:
    pool.map(myMethod, argumentList)
但是,myMethod不会出现在配置文件日志中的任何位置。此外,没有从myMethod中调用的方法被正确地分析。相反,程序在myMethod中花费的所有时间都在日志中“select.poll”对象的“poll”方法下。也就是说,分析不能很好地与sharedmem的映射方法配合使用,我必须找到一种不同的方法来优化我的程序

无论如何,要分析该程序,我看到两个主要选项:

将pool.map替换为经典映射或for循环或 在myMethod周围编写一个包装器,用于对此子例程进行分析并保存或打印结果。 当然,第一个选项不捕获特定于并行化的行为,例如,如果一个进程必须等待另一个进程,并且执行时间更大。然而,如果并行化是“琐碎的”,进程之间没有交互,并且我们对在代码的不同部分花费的相对时间感兴趣,那么这可能是一种方法。请注意,将原始分析结果与修改后的函数的分析结果相比较,如果我们考虑核的数量,则可以推断出在原始代码中花费了多少时间。p> 第二个选项的缺点是,我们可能会得到许多分析结果,尽管我们希望有一个单一的概述。然而,通常可以将代码分块并行化。也就是说,我们可以将参数列表拆分为子列表,以便每个核心进程只执行一次包装器

def myMethodWrapper(argumentListPart):
   return [myMethod(arg) for arg in argumentListPart]

def myMethodProfiler(argumentListPart):
   # replace the line below with the profiling command you are using
   return profile(myMethodWrapper, argumentListPart)
这样,您的结果将与您的计算机上的内核数量相同。请注意,包装器必须在模块级别上定义,或者如果myMethod属于对象级别上的对象,否则将出现pickle错误


我非常确信,如果将相应的结果保存到文件中,则可以通过计算聚合分析结果。然而,到目前为止,我还没有实现这一点。如果答案包含这样的代码,我们将不胜感激。

cProfile不会捕获在不同进程内执行的方法,例如使用ProcessPoolExecutor执行的方法。因此select.poll只是显示等待其他进程结果的主进程。

从I/O读取事件意味着什么?我确实阅读了select.poll上的文档,但对我没有帮助。I/O是否仅仅意味着读取/写入文件和命令行字符?即使我不能更改方法本身,我也可能希望更改调用它的位置/频率。然而,我从未在代码中明确地调用过这个方法。它必须在某个子例程中调用。你能猜到这样的子例程可以处理什么吗?通常是文件,但可以是任何带有fileno/file描述符的东西。查看源文件/Python35/Lib/selectors.py是否可以分享最后使用的不同方式?我使用的是Python多处理,并测试了我的核心进程。我在结果中看到了相同的行为。我没有实现任何池映射。核心是从队列接收数据。据我所知,这似乎是流程使用的内部方法,但我不完全理解在何处/如何使用。@eduardosufan Pool也使用队列从不同流程检索结果。所以这里写的关于Pool的内容也适用于你们。