numpy float:算术运算比内置函数慢 10 倍?

2024-05-01

我对以下代码的计时非常奇怪:

import numpy as np
s = 0
for i in range(10000000):
    s += np.float64(1) # replace with np.float32 and built-in float
  • 内置浮子:4.9秒
  • float64: 10.5 秒
  • float32: 45.0 秒

Why is 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?

EDIT #1:

numpy.float64 是10 times在算术计算中比 float 慢。糟糕的是,即使在计算之前转换为浮点型再转换回来,程序的运行速度也会快 3 倍。为什么?我能做些什么来解决它吗?

我想强调的是,我的时间安排不是由于以下任何原因造成的:

  • 该函数调用
  • numpy 和 python float 之间的转换
  • 对象的创建

我更新了我的代码以更清楚问题所在。使用新代码,我似乎看到使用 numpy 数据类型的性能提高了十倍:

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)

时间安排是:

  • float64: 34.56s
  • float32: 35.11s
  • 浮动:3.53s

只是为了它,我也尝试过:

从日期时间导入日期时间 将 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秒;实际上转换速度快了 3 倍float64 to float然后返回而不是按原样使用它。尽管如此,转换还是要付出代价的,所以总的来说,与纯 python 相比,它慢了 3 倍多float.

我的机器是:

  • 英特尔酷睿 2 双核 T9300 (2.5GHz)
  • WinXP 专业版(32 位)
  • ActiveState Python 3.1.3.5
  • numpy 1.5.1

EDIT #2:

感谢您的回答,他们帮助我了解如何处理这个问题。

但我仍然想知道下面的代码运行速度慢 10 倍的确切原因(也许基于源代码)float64比与float.

EDIT #3:

我在 Windows 7 x64 (Intel Core i7 930 @ 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)

时间安排是:

  • 浮点64:16.1秒
  • 浮动32:16.1秒
  • 浮球:3.2秒

现在两者np浮点数(64 或 32)比内置浮点数慢 5 倍float。尽管如此,还是存在显着差异。我正试图弄清楚它从哪里来。

编辑结束


CPython 浮点数以块的形式分配

将 numpy 标量分配与float类型是CPython总是分配内存float and int大小为 N 的块中的对象。

在内部,CPython 维护一个块链表,每个块足够大以容纳 Nfloat对象。你打电话时float(1)CPython 检查当前块中是否有可用空间;如果不是,则分配一个新块。一旦当前块中有空间,它就会简单地初始化该空间并返回指向它的指针。

在我的机器上每个块可以容纳 41float对象,所以第一个有一些开销float(1)调用但接下来的 40 个运行速度要快得多,因为内存已分配并准备就绪。

慢 numpy.float32 与 numpy.float64

看起来 numpy 在创建标量类型时可以采用 2 条路径:快速和慢速。这取决于标量类型是否具有可以推迟参数转换的 Python 基类。

因为某些原因numpy.float32被硬编码以采用较慢的路径(定义为_WORK0 macro) https://github.com/numpy/numpy/blob/v1.5.1/numpy/core/src/multiarray/scalartypes.c.src#L2101, while numpy.float64有机会走更快的路(定义为_WORK1 macro) https://github.com/numpy/numpy/blob/v1.5.1/numpy/core/src/multiarray/scalartypes.c.src#L2101。注意scalartypes.c.src是一个生成的模板scalartypes.c在构建时。

您可以在 Cachegrind 中直观地看到这一点。我提供了屏幕截图,显示了构建一个float32 vs. float64:

float64采取快速路径

float32走慢路

Updated- 哪种类型采用慢速/快速路径可能取决于操作系统是 32 位还是 64 位。在我的测试系统 Ubuntu Lucid 64 位上,float64类型快 10 倍float32.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

numpy float:算术运算比内置函数慢 10 倍? 的相关文章

随机推荐