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

More memory efficient way to define many objects of the same type

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

我的问题是,在时变环境(好吧,时间步长)中模拟大量粒子时,跟踪所有这些数据是一个技巧。我以前使用过多维数组 - 使用粒子的列号和属性的行号,但这感觉相当笨拙。但是,它确实执行得更快。

我最近尝试定义自己的 class,但是作为 python 新手,我可能以非常低效的方式进行了定义。对于 3 维中的每个粒子,我需要能够存储粒子的位置、速度和力(一旦代码变得更复杂,就有可能添加更多变量)。使用我对 classes 的了解,我定义了一个 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)

因此,我可以轻松地初始化包含大量此类对象的数组,并以相当直接的方式修改每个值。然而,正如我提到的,这 运行 对于只涉及几个粒子的模拟来说更慢。我将玩弄我的代码,将其与纯面向矩阵的方法进行比较,看看哪种方法更适合大型模拟。

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

使用 __slots__

节省内存

一种节省内存的方法是使用 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        

来自文档:

This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. __slots__ reserves space for the declared variables and prevents the automatic creation of __dict__ and __weakref__ for each instance.

旁注:我通过将 mutable default argument problem 设置为 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'

与没有 __slots__ 的 class 比较:

class A:   # Python 3
    pass

a = A()
a.new_attr = 10

没有异常。

听起来您想要享元模式。也许将对象中的一个整数存储为包含 9 个元素的行的数组的索引?