Python类的性能影响:Scientific Computing

问题描述:

所以我正在编写一个粒子模型。该模拟将涉及创建具有诸如物种指数(用于识别粒子类型)的属性以及3D空间中的位置/速度的许多粒子。它也将具有基于其在模拟运行期间将被计算的空间内的位置的属性。我以前一直在使用一个巨大的numpy数组来运行这个模型,其中每一行对应一个单独的粒子,每一列都有一个粒子属性。我的主要问题是:如果我要创建一个类“粒子”,以便可以生成表示每个粒子的实例,那么在计算速度方面是否存在性能问题?如果我想运行一个包含一百万个粒子的程序,将一个大数组中的所有数字(尽管它不可​​读)的效率更高,或者使用这个类的实例效率更高,模拟进程中的实例属性?还是说这些类很好,但是将很多类实例存储在Python列表/ NumPy数组中真的会减慢执行速度?另外,这个程序将与python模块“Numba”一起使用,该模块对数值计算有大量的优化(特别是通过类似于jitclass http://numba.pydata.org/numba-doc/latest/user/jitclass.html#numba.jitclass的东西)。但是,我不想通过在我的模拟中声明变量导致其运行效率低下来破坏此模块的性能优势。Python类的性能影响:Scientific Computing

谢谢!

+0

如果可以优化类下降到结构,不会有真正使用jitclasses性能损失。也就是说,在我的领域中,大多数工作通常编写C++扩展,然后使用像SWIG或Boost :: Python这样的包装将它们封装在Python中。最终,编写简单的测试用例和配置文件,配置文件,配置文件。 –

+0

我不知道'numba'可以做什么,但通常对象dtype数组比数字要慢得多。像列表一样,这些数组值实际上是指向内存中别处的对象的指针。在https:// *中查看我最近的回答。COM /问题/ 46350208/numpy的阵列-VS-列表换定制类。 – hpaulj

+0

创建粒子类的动机是什么 - 更好的抽象?如果是这样,您可以创建一个代表粒子群体的类,并使用获取/修改粒子信息的方法。这将使您能够创建更高级别的抽象来处理粒子,但也会将基础粒子数据存储在数组中,因此您不会将数据分散到内存中。 – charlesreid1

我以前一直使用的巨型numpy的阵列

听起来像是一个好主意,运行这个模型。

如果我要创建一个类“粒子”,以便能够生成表示每个粒子的实例,那么在计算速度方面是否存在性能问题?

它可能会慢得多。

您现有的与NumPy的阵列解决方案可以代表一个大阵列中的所有的粒子:

id species x y z dx dy dz 
id species x y z dx dy dz 
id species x y z dx dy dz 

如果你改变它使用每个粒子一个类的实例,你仍然可以让他们在与NumPy阵列(或列表),但它看起来像这样:

object -> [id species x y z dx dy dz] 
object -> [id species x y z dx dy dz] 
object -> [id species x y z dx dy dz] 

这是您需要分配的四个N + 1对象而不是1(数组)。

我会坚持原始设计,巨型NumPy阵列,除非它引起重大问题。

+0

老实说,可能是用Cython/Swig/Boost潜入C++的最佳答案。 Jitclasses可能会更快,但我不认为它们被视为NumPy中的对象,这意味着指针并因此存在非连续的存储,所以访问速度慢,额外的开销。一个C++扩展可以解决很多这些问题,并且实现起来很简单,但对于这样一个简单的例子是不值得的(更不用说包装问题了)。 –

你应该在这里使用的结构化数据类型:

particle_dtype = np.dtype([ 
    ('id', int), 
    ('species', (np.unicode_, 16)), 
    ('pos', np.float32, 3), 
    ('vel', np.float32, 3) 
]) 

particles = np.empty(100, dtype=particle_dtype) 
particles[0]['id'] = 1 
particles['pos'] += particles['vel'] * dt