对于下面的代码,我得到了非常奇怪的计时:
import numpy as np
s = 0
for i in range(10000000):
s += np.float64(1) # replace with np.float32 and built-in float
为什么float64
比float
慢两倍?为什么float32
比float64慢5倍?
有什么方法可以避免使用np.float64
,并让numpy
函数返回内置的float
,而不是float64
的惩罚吗?
我发现使用numpy.float64
比Python的float慢得多,numpy.float32
甚至慢得多(即使我在32位计算机上)。
numpy.float32
在我的32位计算机上。因此,每次我使用各种numpy函数,比如numpy.random.uniform
,我都会将结果转换为float32
(以便以32位精度执行进一步的操作)。
有没有办法在程序或命令行中设置单个变量,并使所有numpy函数返回float32
,而不是float64
?
编辑1:
numpy.float64在算术计算中比float慢10倍。很糟糕的是,即使在计算之前转换成float和back,程序运行速度也会提高3倍。为什么?我能做些什么来修理它吗?
我想强调的是,我的时间安排不是由于以下原因:
我更新了我的代码,使它更清楚的问题所在。在新代码中,我看到使用numpy数据类型的性能下降了10倍:
from datetime import datetime
import numpy as np
START_TIME = datetime.now()
# one of the following lines is uncommented before execution
#s = np.float64(1)
#s = np.float32(1)
#s = 1.0
for i in range(10000000):
s = (s + 8) * s % 2399232
print(s)
print('Runtime:', datetime.now() - START_TIME)
时间安排如下:
就为了这个,我还试着:
从datetime导入datetime 将numpy导入为np
START_TIME = datetime.now()
s = np.float64(1)
for i in range(10000000):
s = float(s)
s = (s + 8) * s % 2399232
s = np.float64(s)
print(s)
print('Runtime:', datetime.now() - START_TIME)
执行时间是13.28秒;实际上,将float64
转换为float
并将其转换回比按原样使用快3倍。尽管如此,转换还是要付出代价的,因此总的来说,它比纯python慢3倍多。
我的机器是:
编辑2:
谢谢你的回答,它们帮助我理解如何处理这个问题。
但我仍然想知道(可能基于源代码)下面的代码在使用float64
时运行速度比使用float
时慢10倍的确切原因。
编辑3:
我在Windows 7 x64(intelcorei7930@3.8GHz)下重新运行了代码。
同样,代码是:
from datetime import datetime
import numpy as np
START_TIME = datetime.now()
# one of the following lines is uncommented before execution
#s = np.float64(1)
#s = np.float32(1)
#s = 1.0
for i in range(10000000):
s = (s + 8) * s % 2399232
print(s)
print('Runtime:', datetime.now() - START_TIME)
时间安排如下:
现在两个np
浮点(64或32)都比内置的float
慢5倍。不过,还是有很大的不同。我在想它是从哪里来的。
编辑结束
也许,这就是为什么应该直接使用Numpy而不是使用循环。
在这样一个沉重的循环中操作Python对象,不管它们是
float
,np.float32
,总是很慢的。NumPy对向量和矩阵的操作很快,因为所有的操作都是由用C编写的库的一部分对大块数据执行的,而不是由Python解释器执行的。在解释器和/或使用Python对象中运行的代码总是很慢,使用非本机类型会使其速度更慢。这是意料之中的。如果你的应用程序很慢,你需要优化它,你应该试着把你的代码转换成一个直接使用NumPy的向量解决方案,并且速度很快,或者你可以使用Cython等工具在C中创建一个循环的快速实现
CPython浮点以块的形式分配
比较numpy标量分配和
float
类型的关键问题是,CPython总是为大小为N的块中的float
和int
对象分配内存在内部,CPython维护一个链接的块列表,每个块都足够大,可以容纳N
float
个对象。当您调用float(1)
时,CPython检查当前块中是否有可用空间;如果没有,则分配一个新块。一旦在当前块中有空格,它只需初始化该空格并返回指向它的指针。在我的机器上,每个块可以容纳41个
float
对象,因此第一个float(1)
调用有一些开销,但是随着内存的分配和准备就绪,下一个40运行得更快。慢速numpy.float32与numpy.float64比较
在创建标量类型时,numpy似乎有两条路径:fast和slow。这取决于标量类型是否有一个Python基类,它可以将其推迟到该基类进行参数转换。
由于某些原因,} macro) ,而} macro) 。注意,
numpy.float32
被硬编码为采用较慢的路径(defined by the ^{numpy.float64
有机会采用较快的路径(defined by the ^{scalartypes.c.src
是一个模板,它在构建时生成scalartypes.c
。你可以在Cachegrind中看到这一点。我还提供了屏幕截图,显示了构造
float32
与float64
的调用次数:float64
走捷径float32
走慢路已更新-哪种类型采用慢速/快速路径可能取决于操作系统是32位还是64位。在我的测试系统Ubuntu Lucid 64位上,
float64
类型比float32
快10倍。相关问题 更多 >
编程相关推荐