【发布时间】:2016-11-30 23:01:47
【问题描述】:
我已经分配了一个给定大小的大型numpy 数组。例如
my_array = numpy.empty(10000, numpy.float)
数组的值可以通过(模拟示例)生成
k * val ** 2 for val in range(0, 10000)
这个设置数组值的步骤做了很多次。例如,for k in range(0,1000)。除了一开始numpy.empty() 所做的分配之外,我不想做任何其他分配。
我考虑过,
my_array = numpy.array([k*val**2 for val in range(0,10000)])
但这看起来至少要分配列表[k * val ** 2 for val in range(0, 10000)]。对吗?
我也看到了numpy.fromiter,但这似乎是为了构造数组。
my_array = numpy.fromiter((k*val**2 for val in range(0,10000)), numpy.float, 10000)
这里真的还有一个分配吗?
要查看numpy.fromiter 是否分配了一个数组,我尝试了以下操作
import numpy as np
iterable1 = (x*x for x in range(5))
iterable2 = (x*x + 1.0 for x in range(5))
my_array = np.fromiter(iterable1, np.float)
print(my_array)
print(hex(id(my_array)))
my_array = np.fromiter(iterable2, np.float)
print(my_array)
print(hex(id(my_array)))
在输出 I 中,打印的两个地址不同。这是否意味着np.fromiter 分配了一个新数组,然后分配给my_array?
【问题讨论】:
-
np.fromiter不做任何进一步的分配。这就是该功能的全部本质。此外,如果您想一次更改所有项目,则无需使用np.empty。 -
@Kasramvd 你确定吗?我只是不知道。
fromiter的文档说它创建了一个数组。我假设它创建了一个 numpy 数组,然后该数组由运算符 = 移动到my_array。但是,如果您知道没有进行新分配的事实,我会相信您。 -
如果你必须支持任意迭代器并且不想要任何临时分配,那将很难避免最简单的
for ind, elem in enumerate(iterable): my_array[ind] = elem。 -
@onekeystrokeatatime 是的,这正是这个函数的作用。它从一个可迭代对象创建一个数组并将其分配给目标变量。如果您正在寻找摆脱这种情况的方法,请查看我的答案。
-
"除了一开始的 numpy.empty() 分配之外,我不想做任何其他分配。" - 你是从 C++ 的角度来看的,数组分配很昂贵,必须避免。这是 Python。与无 JIT 字节码解释、动态调度和单独分配的 24 字节
int对象的开销相比,数组分配微不足道。