定义多个相同类型对象的内存效率更高的方法

Yos*_*shi 5 python arrays simulation types class

所以,我正在涉足等离子体模拟的世界。现在,虽然我知道顶级模拟是用 Fortran 编写的,并且具有超内存效率的子例程和专用代码,但我希望只运行一些低级模拟。

我的问题是,在时变环境(好吧,时间步进)中模拟大量粒子时,跟踪所有数据是一个技巧。我之前使用过多维数组——使用粒子的列号和属性的行号,但是这感觉很笨拙。然而,它似乎执行得更快。

我最近尝试定义我自己的类,但是作为一个 Python 新手,我可能以一种非常低效的方式做到了。对于 3 维中的每个粒子,我需要能够存储粒子的位置、速度和力(一旦代码变得更复杂,就有可能添加更多变量)。使用我对类的了解,我定义了一个particle对象(我认为),它使我的代码更易于阅读和遵循:

# Define Particle as a class
class particle():
    def __init__(self, index=0, pos=np.array([0, 0, 0]), vel=np.array([0,0,0]), 
                 F=np.array([0, 0, 0])):
        self.index = index      # Particle index (identifier)
        self.pos = pos          # Position 3-vector
        self.vel = vel          # Velocity 3-vector
        self.F = F              # Net force 3-vector (at particle)
Run Code Online (Sandbox Code Playgroud)

因此,我可以轻松地初始化包含大量这些对象的数组,并以相当简单的方式修改每个值。然而,正如我所提到的,这对于仅涉及少数粒子的模拟运行速度较慢。我将使用我的代码将其与纯粹面向矩阵的方法进行比较,以查看哪种方法在大型模拟中的扩展性更好。

我想我的问题是:以这种方式定义“粒子”是最有效的吗?或者是否有更高效的 CPU/内存方式来定义这样的对象。我想保留它的方法能力(即particle[i].pos = [1,2,3]particle[2].vx[1] = 3),以便我可以为每个粒子设置值,并将它们传递给函数。请记住,我是 Python 新手,所以我可能不会在大型复杂代码上取得巨大成功。

Mik*_*ler 4

节省内存__slots__

节省内存的一种方法是使用插槽

class Particle():  # Python 3
    __slots__ = ['index', 'pos', 'vel', 'F']
    def __init__(self, index=0, pos=None, vel=None, F=None):
        # Particle index (identifier)
        self.index = index      
        # Position 3-vector
        self.pos = np.array([0, 0, 0]) if pos is None else pos    
        # Velocity 3-vector
        self.vel = np.array([0,0,0]) if vel is None else vel   
        # Net force 3-vector (at particle)
        self.F = np.array([0, 0, 0]) if F is None else F        
Run Code Online (Sandbox Code Playgroud)

来自文档:

可以为此类变量分配一个字符串、可迭代对象或带有实例使用的变量名称的字符串序列。__slots__为声明的变量保留空间并防止自动创建__dict____weakref__为每个实例。

旁注:我通过将它们设置为并在for值中创建一个新的 NumPy 数组来解决可变默认参数问题None__init__()None

无法向实例添加新属性

一个重要的区别是,您无法在实例化后添加未在以下列表中列出的属性__slots__

p = Particle()

p.new_attr = 45

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-664-a970d86f4ca3> in <module>()
      1 p = Particle()
      2 
----> 3 p.new_attr = 45

AttributeError: 'Particle' object has no attribute 'new_attr'
Run Code Online (Sandbox Code Playgroud)

与没有的类相比__slots__

class A:   # Python 3
    pass

a = A()
a.new_attr = 10
Run Code Online (Sandbox Code Playgroud)

没有例外。