Timeit显示常规python比numpy快?
我正在为一个游戏编写一段代码,该代码使用游戏中的坐标位置计算屏幕上所有对象之间的距离。最初,我打算使用基本Python和列表来实现这一点,但由于需要计算的距离数量将随着对象数量的增加而呈指数增长,因此我认为使用numpy可能会更快 我对numpy不是很熟悉,我一直在用它进行基本代码位的实验。我编写了一些代码来计算同一个函数在numpy和常规Python中完成计算所需的时间,numpy似乎总是比常规Python花费更多的时间 功能非常简单。它从1.1开始,然后递增200000次,最后一个值加上0.1,然后找到新值的平方根。这不是我在游戏代码中实际要做的,它将涉及从位置坐标中找到总距离向量;这只是我做的一个快速测试。我已经读到,数组的初始化在NumPy中需要更多的时间,所以我将NumPy和python数组的初始化都移到了它们的函数之外,但是python仍然比NumPy快 下面是一段代码:Timeit显示常规python比numpy快?,python,performance,numpy,timeit,Python,Performance,Numpy,Timeit,我正在为一个游戏编写一段代码,该代码使用游戏中的坐标位置计算屏幕上所有对象之间的距离。最初,我打算使用基本Python和列表来实现这一点,但由于需要计算的距离数量将随着对象数量的增加而呈指数增长,因此我认为使用numpy可能会更快 我对numpy不是很熟悉,我一直在用它进行基本代码位的实验。我编写了一些代码来计算同一个函数在numpy和常规Python中完成计算所需的时间,numpy似乎总是比常规Python花费更多的时间 功能非常简单。它从1.1开始,然后递增200000次,最后一个值加上0.
#!/usr/bin/python3
import numpy
from timeit import timeit
#from time import process_time as timer
import math
thing = numpy.array([1.1,0.0], dtype='float')
thing2 = [1.1,0.0]
def NPFunc():
for x in range(1,200000):
thing[0] += 0.1
thing[1] = numpy.sqrt(thing[0])
print(thing)
return None
def PyFunc():
for x in range(1,200000):
thing2[0] += 0.1
thing2[1] = math.sqrt(thing2[0])
print(thing2)
return None
print(timeit(NPFunc, number=1))
print(timeit(PyFunc, number=1))
它给出了这个结果,这表明普通Python的速度快了3倍:
[ 20000.99999999 141.42489173]
0.2917748889885843
[20000.99999998944, 141.42489172698504]
0.10341173503547907
我做错了什么吗?这个计算是不是太简单了,不能作为numpy的一个好测试?你比较错了
a_list = np.arange(0,20000,0.1)
timeit(lambda:np.sqrt(a_list),number=1)
我做错了什么吗?这个计算是不是太简单了,对NumPy来说不是一个好的测试
这并不是说计算很简单,而是你没有利用NumPy
但是,如果你将其与实际利用NumPy进行比较——例如,创建一个包含200000个浮点的数组,然后在该数组上调用np.sqrt,而不是在每个数组上循环并调用math.sqrt,那么你将证明按照预期的方式使用NumPy比不使用更快。作为旁注,在你计划的东西里面打印通常是个坏主意。打印东西所需的时间变化很大,也可能比实际工作所需的时间更长。在这种情况下,这可能没什么大不了的,因为你正在使用number=1,并且在函数中做了很多工作,但是最好还是去掉print调用。这是有道理的。另外,与其在函数中循环200000次并使用number=1,不如让timeit至少控制其中的一部分,例如。,循环2000次,美国编号=100。这给了它更多的工作机会。不过,我还是怀疑在这种特殊情况下,它会有多大的不同。最后一件事:用数组替换列表,用数组函数替换循环,这样可以获得恒定的加速因子。这可能是一个令人印象深刻的加速,比如6倍甚至60倍,但如果你的问题是指数增长,那可能只会让你的最大可行N增加1或2…Numpy擅长矢量化命令。使用Numba或Cython编译器,简单循环通常可以获得100-1000倍的系数。这很有意义。我试过上面Joran Beasley评论的代码行,速度明显更快。因此,诀窍是尽可能少地将值创建/加载到numpy数组中,但要使这些数组尽可能大
可以这样,一旦您开始对阵列执行操作,程序就可以高效地在一个大型阵列中运行,而无需启动和停止?@CMB。许多问题可以转化为一系列的元素操作或一次一个数组的操作,因此,如果您可以用NumPy数组来编写它们,您将获得很大的加速。有些问题不能这样写,所以你只能从NumPy中得到开销。除了你仍然可以从大量的浮点对象和海量数据中获得空间优势,这反过来可以在分配、缓存、交换等方面节省大量时间。但是,另一方面,有时你可以懒散地编写非NumPy代码,因此它根本不占用空间,那么,与将普通python值加载到数组中所需的时间相比,计算量的增加有多大的好处呢?对于真正的代码,游戏中的每个对象都将是一个类实例,它包含自己的位置向量。所有对象都将存储在一个列表中。我最初的计划是让一段代码沿着列表向下,找出每个列出的对象到所有其他对象的距离。将所有这些位置转移到NumPy数组并执行计算可能更快还是更慢?@CMB如果有很多这样的对象,将所有这些位置向量存储在一个大的2D数组中可能更快,让类实例只跟踪它们的行索引或对数组中的行的引用,而不是直接保存向量。但是,这取决于您还必须对实例执行什么操作。如果您需要循环代码中某个时间关键部分的所有实例,那么仅将该循环的一部分拉到另一个数组操作可能不会有多大好处;您需要将所有内容移动到数组操作以获得较大的加速。将值从NumPy数组移动到其他NumPy数组是否有任何区别?也就是说,如果我将位置存储在它们各自的类实例中作为NumPy数组,那么将它们转移到更大的数组会更容易,还是只会增加更多工作?