Python中集群计算的快速JSON序列化(以及与Pickle的比较)?

2024-04-28 20:31:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组数据点,每个数据点都由字典描述。每个数据点的处理是独立的,我将每个数据点作为单独的作业提交给集群。每个数据点都有一个唯一的名称,我的集群提交包装器只调用一个脚本,该脚本接受一个数据点的名称和一个描述所有数据点的文件。然后,该脚本从文件访问数据点并执行计算。在

由于每个作业都必须加载所有点的集合来检索要运行的点,因此我希望通过将描述点集的文件序列化为易于检索的格式来优化这一步骤。在

我尝试使用JSONpickle,使用以下方法序列化一个字典,该字典描述要文件的所有数据点:

def json_serialize(obj, filename, use_jsonpickle=True):
    f = open(filename, 'w')
    if use_jsonpickle:
    import jsonpickle
    json_obj = jsonpickle.encode(obj)
    f.write(json_obj)
    else:
    simplejson.dump(obj, f, indent=1)   
    f.close()

字典包含非常简单的对象(列表、字符串、浮点等),共有54000个键。json文件的大小约为20兆字节。在

将这个文件加载到内存需要大约20秒,这对我来说很慢。我转而使用pickle处理相同的对象,发现它生成的文件大小约为7.8兆字节,可以在大约1-2秒内加载。这是一个显著的改进,但是看起来加载一个小对象(少于100000个条目)应该更快。除此之外,pickle是不可读的,这是JSON对我最大的优势。在

有没有一种方法可以使用JSON来获得相似或更好的加速?如果没有,你有没有其他的想法来组织这个?在

(简单地将描述每个事件的文件“切片”到一个单独的文件中并将其传递给在集群作业中运行数据点的脚本是正确的解决方案吗?这似乎会导致文件激增)。在

谢谢。在


Tags: 文件数据对象方法脚本名称jsonobj
2条回答

marshal是最快的,但是pickle本身可能不是{}(这是相当快的,特别是使用-1协议)。因此,除了可读性问题之外,下面是一些代码来展示各种可能性:

import pickle
import cPickle
import marshal
import json

def maked(N=5400):
  d = {}
  for x in range(N):
    k = 'key%d' % x
    v = [x] * 5
    d[k] = v
  return d
d = maked()

def marsh():
  return marshal.dumps(d)

def pick():
  return pickle.dumps(d)

def pick1():
  return pickle.dumps(d, -1)

def cpick():
  return cPickle.dumps(d)

def cpick1():
  return cPickle.dumps(d, -1)

def jso():
  return json.dumps(d)

def rep():
  return repr(d)

下面是我笔记本电脑上的速度:

^{pr2}$

因此,使用repr可以使可读性json.dumps的10倍(您牺牲了Javascript和其他语言的解析容易性);使用marshal可以获得绝对最高速度,几乎比json快90倍;cPicklejson或{}提供了更多的通用性(就可以序列化的内容而言),但是如果您永远不会使用这种通用性,那么您最好选择marshal(或者{},如果人类的可读性胜过速度)。在

至于你的“切片”思想,代替大量的文件,你可能需要考虑一个数据库(大量的记录),如果你运行的数据有一些可识别的“模式”,你甚至可以在没有实际序列化的情况下逃脱。在

我认为您在这里面临一个权衡:人类的可读性是以性能和大文件大小为代价的。因此,在Python中可用的所有序列化方法中,JSON不仅可读性最强,而且速度最慢。在

如果我必须追求性能(和文件紧凑性),我会选择marshall。您可以使用dump()load()封送整个数据集,或者根据您的分层思想,将数据集的各个部分封送到单独的文件中。这样,如果您愿意,就为数据处理的并行化打开了大门。在

当然,文档中有各种各样的限制和警告,所以如果您决定安全起见,请使用pickle。在

相关问题 更多 >