在我离开这一天之前,我找不到答案的简短问题,
当我做这样的事情时:
v1 = float_list_python = ... # <some list of floats>
v2 = float_array_NumPy = ... # <some numpy.ndarray of floats>
# I guess they don't have to be floats -
# but some object that also has a native
# object in C, so that numpy can just use
# that
如果我想用标量乘以这些向量,我的理解一直是python列表是一个对象引用列表,因此循环遍历列表进行乘法必须获取所有浮点数的位置,并且然后必须得到漂浮物才能做到 - 这是它变慢的原因之一。
如果我在NumPy中做同样的事情,那么,我不确定会发生什么。我想象有很多事情可以发生:
我发现的文档表明numpy中的许多原语随时都可以利用第一个选项(我现在可以测试它时手头没有计算机)。而且我的直觉告诉我,只要有可能就会发生2号。
所以我的问题是,如果我创建一个NumPy python对象数组,它是否仍然至少并行执行列表上的操作?我知道如果你创建一个对象数组本机C类型,然后它实际上会在实际对象的内存中创建一个连续的数组,如果你创建一个numpy数组的python对象,它将创建一个引用数组,但我不明白为什么这将排除并行在所述列表上的操作,并且找不到明确指出该列表的任何地方。
编辑:我觉得我的问题有些混乱。我理解向量化是什么,我理解它是一个编译器优化,而不是你必须编程的东西(虽然对齐数据使得它在内存中是连续的很重要)。在矢量化的基础上,我想知道的是numpy是否使用它。如果我执行np_array1 * np_array2
之类的操作,底层库调用会使用向量化(假设dtype
是兼容类型)。
对于核心的分裂,我的意思是,如果我再次做np_array1 * np_array2
之类的事情,但这一次dtype=object
:它会将那些工作分成核心吗?
答案 0 :(得分:1)
numpy
速度很快,因为它在快速编译的C
代码中执行这样的数值运算。相比之下,列表操作在解释的Python级别上运行(尽可能使用Python字节码等进行简化)。
数字类型的numpy
数组将这些数字存储在数据缓冲区中。至少在简单的情况下,这只是C
代码可以有效地逐步执行的字节块。该数组还具有形状和跨步信息,允许多维访问。
当你将数组乘以标量时,它实际上会调用C
函数,其函数类似于&quot; multiply_array_by_scalar&#39;,它在快速编译的代码中进行乘法运算。因此,无论核心数量或其他多处理/线程增强,这种numpy
操作都很快(与Python列表代码相比)。
对象数组没有任何特殊的速度优势(与列表相比),至少目前还没有。
查看关于创建数组数组的问题的答案,https://stackoverflow.com/a/28284526/901925 我不得不使用迭代来初始化值。
你有没有做过实验?例如,构造一个数组,比如(1000,2)
。使用tolist()
创建等效的列表列表。并创建一个类似的对象数组,每个对象是一个(2,)数组或列表(这需要做多少工作?)。现在为每个子列表做一些简单的事情,比如len(x)
。
答案 1 :(得分:0)
@hpaulj为您的问题提供了一个很好的答案。一般来说,通过阅读你的问题,我发现你实际上并没有理解&#34;矢量化&#34;引擎盖下。这篇文章是矢量化的一个相当不错的解释,以及它如何实现更快的计算 - http://quantess.net/2013/09/30/vectorization-magic-for-your-computations/
关于第1点 - 在多个核心之间分配计算,Numpy并非总是如此。但是,像numexpr这样的库可以支持多个基本的逻辑和算术运算符,从而实现多线程,高效的Numpy数组计算。当与Numpy一起使用时,Numexpr可用于对关键计算进行turbo充电,因为它避免了在内存中复制大型数组用于向量化例程(如Numpy的情况),并且可以使用系统上的所有内核来执行计算。