我已经分配了一个给定大小的numpy
大数组。例如
my_array = numpy.empty(10000, numpy.float)
数组的值可以由(模拟示例)生成
^{pr2}$设置数组值的这一步要做很多次。例如,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
?在
^{} 不执行任何进一步的分配。它只是从iterable创建一个数组。这就是函数的全部本质。它还接受一个
count
参数,该参数允许fromiter
预先分配输出数组,而不是根据需要调整其大小。在另外,如果您想一次更改所有项目,则不需要使用
np.empty
。在毕竟,如果您是通过对一系列数字执行一些数学运算来构造新数组,那么您也可以对Numpy数组执行这些操作。在
下面是一个例子:
首先确保您了解变量赋值的作用:
第二个作业代替第一个作业。
^{pr2}$my_array
最初引用的对象是空闲的,并被垃圾回收。这只是基本的Python变量处理。要保持原始数组(可变对象),必须更改其值但是生成
<new values>
的进程很可能会创建一个临时缓冲区(或两个或三个)。然后将这些值复制到目标。甚至x += 1
也进行缓冲计算。几乎没有现成的裸体手术。在一般来说,试图猜测numpy的内存分配是行不通的。效率只能通过时间测试来衡量,而不是通过猜测幕后发生了什么。在
除非需要迭代地填充“预分配”,否则不要费心:
这是一种糟糕的创建数组的方法,相比之下:
fromiter
方法更漂亮,但不是更快。在一些时间安排:
fromiter
所需时间与显式循环一样长,而纯numpy解要快几个数量级。从时间上看,使用列表理解的np.array
与使用生成器的fromiter
之间几乎没有差别。在从预先存在的列表创建数组需要大约1/3的时间。在
将列表分配给现有的
empty
数组并不快。在有些
numpy
函数接受out
参数。以这种方式重用数组可以节省一些时间。np.cross
是一个利用这一点的函数(代码是Python的,可读)。在从标量函数创建值的另一种“矢量化”方法:
根据评论中的解释,问题似乎如下:
第二个问题是:只要您的值来自Python,将它们放入numpy数组将不会真正有效。这是因为您必须循环处理解释代码中的每个值。在
CPython的虚拟机与C++模型有很大不同;具体来说,编译器不能将表达式内嵌或将其解释为整体,以使其显著地更有效。即使它支持在C中执行这一特定操作的字节码指令,它仍然需要调用生成器的
next
方法,该方法在执行Python字节码之后,将每个值生成为堆分配的Python对象。在这两种情况下,每次迭代都会涉及到解释的代码,而您确实希望避免这种情况。在解决问题的有效方法是从头开始设计,不要离开numpy。正如其他人在评论中所解释的那样,与在Python中逐个处理数据的实际成本相比,分配的成本(如果有效的话,由numpy完成)是微不足道的。我将设计如下:
numpy.fromiter
尽早将迭代器转换为numpy数组。在my_array[:] = new_array[:]
或{my_array
在数据模型中的许多地方被共享时,它就更有意义了。)如果在完成上述操作之后,numpy不支持某些操作,并且测量结果表明它效率极低,那么可以使用Python/C API创建一个扩展模块,该模块高效地执行计算并以C中创建的numpy数组的形式返回结果
相关问题 更多 >
编程相关推荐