Python类的性能影响:科学计算

Python类的性能影响:科学计算,python,performance,numpy,numba,Python,Performance,Numpy,Numba,所以我正在写一个粒子模型。此模拟将涉及创建一些具有诸如种类索引(用于识别粒子类型)和三维空间中的位置/速度等属性的粒子。它还将具有基于其在模拟运行期间将计算的空间中的位置的属性。我以前使用一个巨大的numpy数组运行过这个模型,其中每行对应一个粒子,每列对应一个粒子属性 我的主要问题是:如果我要创建一个类“Particles”,以便生成代表每个粒子的实例,那么在计算速度方面是否会影响性能?如果我想运行一个有一百万个粒子的程序,那么将所有的数字放在一个大数组中(即使它不是那么可读)是更有效,还是使

所以我正在写一个粒子模型。此模拟将涉及创建一些具有诸如种类索引(用于识别粒子类型)和三维空间中的位置/速度等属性的粒子。它还将具有基于其在模拟运行期间将计算的空间中的位置的属性。我以前使用一个巨大的numpy数组运行过这个模型,其中每行对应一个粒子,每列对应一个粒子属性

我的主要问题是:如果我要创建一个类“Particles”,以便生成代表每个粒子的实例,那么在计算速度方面是否会影响性能?如果我想运行一个有一百万个粒子的程序,那么将所有的数字放在一个大数组中(即使它不是那么可读)是更有效,还是使用这个类的实例并在模拟过程中修改实例属性同样有效?还是说类很好,但在Python列表/NumPy数组中存储那么多类实例确实会降低执行速度

另外,这个程序将与python模块“Numba”一起使用,该模块对数值计算进行了大量优化(特别是通过JIT类之类的东西)。但是,我不想通过在模拟中声明导致其运行效率低下的变量来破坏该模块的性能优势

谢谢

我以前用一个巨大的numpy阵列运行过这个模型

听起来是个好主意

如果我要创建一个类“Particles”,以便生成代表每个粒子的实例,那么在计算速度方面是否会影响性能

它可能会慢得多

使用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阵列,除非它会导致重大问题。

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

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

如果您可以将类优化到结构,那么使用JIT类不会造成性能损失。也就是说,我的领域中的大多数工作都是传统的C++扩展,然后使用像SWIG或Boosi::Python这样的包装器在Python中包装它们。最后,编写简单的测试用例和概要文件,概要文件,概要文件。我不知道
numba
能做什么,但通常情况下,对象数据类型数组比数字数组慢得多。与列表类似,这些数组值实际上是指向内存中其他位置对象的指针。请参阅中我最近的答案。创建粒子类的动机是什么?更好的抽象?如果是这样,您可以创建一个表示粒子总体的类,其中包含获取/修改粒子信息的方法。这将使您有能力创建更高级别的抽象来处理粒子,但也可以将基础粒子数据存储在一个数组中,这样就不会将数据分散到内存中。如果您真的关注性能,那么最好花点时间用C或C++编译语言实现代码。Cython可能是一个很好的中间步骤。但归根结底,基准测试是为应用程序获得“正确”答案的唯一方法。试着制作一些代表你真正问题的玩具问题,看看这两种方法是如何比较的。坦白地说,最好的答案是,在Cython/SWIG/Boost中跳入C++。JIT类可能更快,但我不相信它们在NumPy中被视为对象,这意味着指针和非连续存储,因此访问速度慢,额外开销大。一个C++扩展将解决很多这些问题,并且实现起来很微不足道,但是对于这样一个简单的例子不值得付出努力(更不用说封装问题)了。