定义许多相同类型的对象的内存效率更高的方法
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 个元素的行的数组的索引?
所以,我正在涉足等离子体模拟领域。现在,虽然我知道顶级模拟是用 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 个元素的行的数组的索引?