更有效的内存方式来定义同一类型的许多对象

时间:2016-01-28 21:41:57

标签: python arrays class types simulation

所以,我正在进军等离子体模拟领域。现在,虽然我知道顶层仿真是用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)

因此,我可以轻松初始化包含大量这些对象的数组,并以合理直接的方式修改每个值。然而,正如我所提到的,对于仅涉及少量粒子的模拟,这种情况会变慢。我将使用我的代码将其与纯粹的面向矩阵的方法进行比较,以查看哪种方法可以通过大型模拟进行更好的扩展。

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

2 个答案:

答案 0 :(得分:4)

使用__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        

来自文档:

  

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

旁注:我将mutable default argument problem设置为None,并在__init__()中为None值创建新的NumPy数组,从而修正了Bobby tables

无法向实例

添加新属性

一个重要的区别是,您无法在实例化后添加未在__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 A:   # Python 3
    pass

a = A()
a.new_attr = 10

没有例外。

答案 1 :(得分:-1)

听起来你想要飞重模式。也许在对象中存储一个整数作为一个包含9行元素的数组的索引?