【问题标题】:Frequently Updating Stored Data for a Numerical Experiment using Python [closed]使用 Python 频繁更新数值实验的存储数据 [关闭]
【发布时间】:2014-06-27 16:52:50
【问题描述】:

我正在运行一个需要多次迭代的数值实验。每次迭代后,我想将数据存储在 pickle 文件或类似 pickle 的文件中,以防程序超时或数据结构被窃听。最好的方法是什么。这是骨架代码:

data_dict = {}                       # maybe a dictionary is not the best choice
for j in parameters:                 # j = (alpha, beta, gamma) and cycle through
    for k in number_of_experiments:  # lots of experiments (10^4)
        file = open('storage.pkl', 'ab')
        data = experiment()          # experiment returns some numerical value
                                     # experiment takes ~ 1 seconds, but increase
                                     # as parameters scale
        data_dict.setdefault(j, []).append(data)
        pickle.dump(data_dict, file)
        file.close()

问题:

  1. 在这里搁置是更好的选择吗?还是我不知道的其他 python 库?
  2. 我正在使用数据字典,因为如果我在进行更多实验时需要更改内容,它更容易编码并且更灵活。使用预先分配的数组会有很大的优势吗?
  3. 打开和关闭文件会影响运行时间吗?我这样做是为了检查除了我设置的文本日志之外的进度。

感谢您的帮助!

【问题讨论】:

  • 对于您的“打开”开销,对于几个字节文件,使用“ab”选项打开大约需要 39 微秒,1kB 需要 41 微秒(us),~10kB 需要 44 微秒,158 us对于 100kB 和 2MB,对于 20MB 文件需要 162 us。因此,如果您的文件大小低于 20MB,则不会很多...这是使用 SSD 的 YMMV。

标签: python pickle numerical-methods


【解决方案1】:
  1. 假设您在数值实验中使用numpy,而不是pickle,我建议您使用numpy.savez
  2. 保持简单,仅当您觉得脚本运行时间过长时才进行优化。
  3. 打开和关闭文件确实会影响运行时间,但最好有备份。

我会使用collections.defaultdict(list) 而不是普通的dictsetdefault

【讨论】:

    【解决方案2】:

    搁置可能不是一个好的选择,但是......

    您可以尝试使用kleptojoblib。两者都擅长缓存结果,并且可以使用高效的存储格式。

    joblibklepto 都可以将结果保存到磁盘上的文件或目录中。两者还可以利用numpy 内部存储格式和/或保存时压缩……如果您愿意,还可以保存到内存映射文件。

    如果您使用klepto,它将字典键作为文件名,并将值保存为内容。使用klepto,您还可以选择是否要使用picklejson 或其他一些存储格式。

    Python 2.7.7 (default, Jun  2 2014, 01:33:50) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import klepto
    >>> data_dict = klepto.archives.dir_archive('storage', cached=False, serialized=True)     
    >>> import string
    >>> import random
    >>> for j in string.ascii_letters:
    ...   for k in range(1000):
    ...     data_dict.setdefault(j, []).append([int(10*random.random()) for i in range(3)])
    ... 
    >>> 
    

    这将创建一个名为storage 的目录,其中包含腌制文件,每个data_dict 的键对应一个。有用于使用memmap 文件的关键字,也有用于压缩级别的关键字。如果您选择cached=False,那么每次写入data_dict 时都不会转储到文件,而是每次都写入内存……然后您可以在选择时使用data_dict.dump() 转储到磁盘……或者您可以选择一个内存限制,当你达到它时,你会转储到磁盘。此外,您还可以选择一种缓存策略(例如 lrulfu)来决定您将从内存中清除哪些键并转储到磁盘。

    在此处获取kleptohttps://github.com/uqfoundation

    或在此处获取joblibhttps://github.com/joblib/joblib

    如果你重构,你可能会想出一种方法来做到这一点,这样它就可以利用预先分配的数组。但是,这可能取决于您的代码运行方式的配置文件。

    打开和关闭文件会影响运行时间吗?是的。如果您使用klepto,您可以设置要转储到磁盘的时间粒度。然后,您可以在速度与结果的中间存储之间进行权衡。

    【讨论】:

    • 感谢您提供这个迷你教程!真的很感激。
    • 不客气。如果您发现上述内容对您不起作用,我可能还记得足够多的 joblib 来添加一个示例。
    • 嘿迈克,知道这个问题已正式关闭,但最近遇到了这个problem 并且我很困惑。我已将其通过电子邮件发送给我知识渊博的朋友,希望有人会回答它,但还没有运气。我想知道您是否在处理此类数据时遇到过这种困难,以及您是如何解决的。事实上,我在这里发表评论,希望这些模块之一可以真正解决这种情况。
    • 我最终优化了实际的python代码,因此不需要使用您建议的模块来实现数据存储以加快运行时间;因此,我坚持使用泡菜只是为了让它第一次工作!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多