在Windows上不一致的Python性能

我有一些我正在使用的Python 2.7代码,它在任何* nixtypes的系统上都很好用。 但是,在Windows上,代码的相同部分将具有非常不同的执行时间。 请注意我的debugging输出如下。 t是每次通过的总时间,s是生成数据的时间,u是通过串行发送数据到我的设备的时间(全部以毫秒为单位)。

t: 9 - s: 3 - u: 6 t: 14 - s: 9 - u: 5 t: 9 - s: 3 - u: 6 t: 9 - s: 3 - u: 6 t: 15 - s: 8 - u: 7 t: 14 - s: 9 - u: 5 t: 11 - s: 5 - u: 6 t: 15 - s: 9 - u: 6 t: 14 - s: 9 - u: 5 t: 13 - s: 8 - u: 5 t: 15 - s: 9 - u: 6 t: 15 - s: 9 - u: 6 t: 14 - s: 8 - u: 6 t: 11 - s: 6 - u: 5 t: 11 - s: 5 - u: 6 t: 15 - s: 8 - u: 7 t: 15 - s: 10 - u: 5 t: 7 - s: 2 - u: 5 t: 15 - s: 9 - u: 6 t: 15 - s: 9 - u: 6 t: 13 - s: 7 - u: 6 t: 12 - s: 7 - u: 5 t: 12 - s: 6 - u: 6 t: 15 - s: 9 - u: 6 t: 8 - s: 2 - u: 6 t: 14 - s: 9 - u: 5 t: 15 - s: 9 - u: 6 t: 14 - s: 9 - u: 5 t: 15 - s: 9 - u: 6 t: 14 - s: 8 - u: 6 t: 14 - s: 9 - u: 5 t: 14 - s: 9 - u: 5 t: 9 - s: 4 - u: 5 t: 11 - s: 5 - u: 6 

串行发送时间不是问题,一般非常一致。 是“s”步骤,它实际上生成有问题的数据,需要2到9毫秒的时间。 相当巨大的摇摆! 在Debian上(甚至在一个覆盆子pi上运行),这部分需要非常一致的11-12毫秒。

这里有很多其他的代码,但是用“s”表示的步骤基本上是这样的:

  buf = [wheel_helper(self._vector[y][x], h, s) for y in range(h) for x in range(w)] buf = [i for sub in buf for i in sub] self._led.setBuffer(buf) 

它在一个matrix上产生一个彩虹图案,其颜色是基于它与中心的距离。 但是一次都是这样。 我没有看到为什么它应该如此疯狂地变化。

有什么想法吗?

更新:通常可以忽略我为“s”步骤运行的代码。 这只是很多的一个例子,所有这些都在不同的时间运行。 有些使用范围,有些不是。 这是全面的,但一直是一个问题。

更新2:

好吧,我做了一些进一步的testing,并做了一个非常简单的例子, 使用范围! 它计算1000次斐波纳契数列的前1000个元素。 很简单,对吧? 但在Windows上,最快运行和最慢运行之间的差距将会延长近375%(下面的示例输出中的最大值/最小值)。 所有的计时值是毫秒。

 import time import math min = 10 max = 0 avg = 0 sum = 0 count = 0 def msec(): return time.clock() * 1000.0 def doTime(start): global min global max global avg global sum global count diff = msec() - start if diff < min: min = diff if diff > max: max = diff sum += diff avg = sum/count print "Curr {:.3f} | Min {:.3f} | Max {:.3f} | Max/Min {:.3f} | Avg {:.3f}".format(diff, min, max, max/min, avg) h = 24 w = 24 while count < 1000: start = msec() #calculate the first 1000 numbers in the fibonacci sequence x = 0 while x < 1000: a = int(((((1 + math.sqrt(5)) / 2) ** x) - (((1 - math.sqrt(5)) / 2) ** (x))) / math.sqrt(5)) x+=1 count+=1 doTime(start) 

原来,Mac并不是免疫的,但是最慢的时间只有75%。 我试图在Linux上运行,但它不会做微秒的时间分辨率,所以数字被舍入到最接近的毫秒。

 Windows: Curr 2.658 | Min 2.535 | Max 9.524 | Max/Min 3.757 | Avg 3.156 Mac: Curr 1.590 | Min 1.470 | Max 2.577 | Max/Min 1.753 | Avg 1.554 

我相信这是由于范围 。 python(2.X)的老版本有这个范围范围 。 但是xrangerange更有效率,因为xrange只在需要的时候才会生成列表(即它返回一个生成器),而range生成整个列表(因此效率低下,假设列表从1到100000)

所以如果你的列表大小在增加, 范围的使用可能是你的进程减慢的原因。

我没有看到任何问题。 你有执行串行IO的代码,这将阻塞你的进程,并可能调用调度程序。 如果发生这种情况,它将首先将控制权交给一个不同的流程,并且只有当流程产生或超过其时间片时,才会重新安排流程。

您的问题是:您正在运行的系统的调度程序时间片的大小是多少? 我相信这会让你深入了解正在发生的事情。