适合模拟系统的数据结构是什么?
我正在计划构建一个模拟程序,需要一些关于如何根据内存和速度来表示数据的想法。
在每个时间步中,模拟过程会创建1000到10000条新数据记录,并查看每条新记录或已有记录(总共有100万到1亿条),然后决定是删除还是修改它们。
每条记录有3到10个简单的字段,每个字段要么是整数,要么是几个ASCII字符组成的字符串。此外,每条记录还有1到5个其他字段,每个字段是一个可变长度的整数列表。一般来说,一条记录的大小在100到500字节之间。
修改或删除的过程是这样的:对于这条记录,计算一个函数,这个函数的参数是这条记录某些字段的值,以及另一条记录的这些字段的值。根据计算结果,决定是删除还是以某种方式修改这条记录的字段。
然后对每一条记录重复这个过程。接着移动到下一条记录,继续重复。当所有记录都处理完后,模拟就准备好进入下一个时间步。
在进入下一个时间步之前,应用所有准备好的删除和修改操作。
记录越多,模拟效果越好。如果所有记录都在内存中,缺点是模拟的大小,优点是速度。模拟不需要实时进行,但显然我不希望它太慢。
为了在内存中表示每条记录,我知道有这些选择:一个列表或字典(里面可以嵌套一些列表),或者一个类的实例。为了保存所有记录,以便下次继续模拟,按照我熟悉程度的顺序,选择有:一个CSV文件,每行是一条记录,或者把所有记录放在内存中,然后再写入文件(可能使用pickle),或者使用某种数据库。
我学过Python的基础知识,还有一些像生成器这样的概念,但还没学过数据库,也没尝试过pickle,显然我需要学习更多。如果可以的话,我希望避免使用多台电脑,因为我只有一台,也不想涉及并发,因为那看起来太复杂了。
你有什么建议关于如何在内存中表示记录,以及如何保存模拟系统吗?
1 个回答
如果我们考虑最糟糕的情况,比如有1亿条记录,每条记录占500字节,那需要的内存会非常大。所以在设计的时候,应该考虑一些灵活性,假设并不是所有的记录都会一直在内存中。你可以创建一个抽象类,来隐藏记录存储的细节。
class Record(object):
def __init__(self, x, y, z):
pass # code goes here
def get_record(id):
pass # code goes here
你可以把方法名从get_record()
改成__index__()
,这样你的类就会像一个列表一样工作,但实际上可能是在访问数据库,或者引用内存缓存,或者其他的方式。只需要用整数作为ID值。如果你后来改变了存储方式(比如从数据库换成其他的存储方式),那么实际的代码就不需要改动。
你也可以尝试创建一个非常大的交换文件,让虚拟内存系统来处理记录在实际内存中进出的问题。这种方法很简单,但没有办法轻松地中断计算并保存当前状态。
你可以把每条记录表示为一个元组,甚至是一个命名元组。我认为元组在Python中是所有“容器”对象中开销最低的。(命名元组只在一个地方存储名字,所以它的开销也很低。)