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

5 python serialization json cluster-computing pickle

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

由于每个作业必须加载所有点的集合才能检索要运行的点,我想通过将描述点集的文件序列化为易于检索的格式来优化此步骤.

我尝试使用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()
Run Code Online (Sandbox Code Playgroud)

字典包含非常简单的对象(列表,字符串,浮点数等),总共有54,000个键.json文件的大小约为20兆字节.

将此文件加载到内存大约需要20秒,这对我来说似乎很慢.我切换到使用具有相同确切对象的pickle,并发现它生成一个大约7.8兆字节的文件,并且可以在1-2秒内加载.这是一个重大的改进,但似乎加载一个小对象(少于100,000个条目)应该更快.除此之外,泡菜不是人类可读的,这对我来说是JSON的最大优势.

有没有办法使用JSON来获得类似或更好的加速?如果没有,你对构建这个有什么想法吗?

(将解决每个事件的文件简单地"切片"到一个单独的文件中并将其传递给在集群作业中运行数据点的脚本是正确的解决方案吗?看起来这可能会导致文件激增).

谢谢.

Ale*_*lli 7

marshal是最快的,但pickle本身不是 - 也许你的意思cPickle(这是非常快,特别是与-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)
Run Code Online (Sandbox Code Playgroud)

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

$ py26 -mtimeit -s'import pik' 'pik.marsh()'
1000 loops, best of 3: 1.56 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.pick()'
10 loops, best of 3: 173 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.pick1()'
10 loops, best of 3: 241 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.cpick()'
10 loops, best of 3: 21.8 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.cpick1()'
100 loops, best of 3: 10 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.jso()'
10 loops, best of 3: 138 msec per loop
$ py26 -mtimeit -s'import pik' 'pik.rep()'
100 loops, best of 3: 13.1 msec per loop
Run Code Online (Sandbox Code Playgroud)

所以,你可以有可读性速度十倍json.dumpsrepr(你牺牲便于从Javascript和其他语言解析的); 你可以拥有绝对的最大速度marshal,几乎快90倍json; cPickle提供比多路通用(在可以序列什么条件)无论是jsonmarshal,但如果你永远不会使用普遍性,那么你还不如去marshal(或者repr,如果人类可读性胜过速度).

至于你的"切片"想法,代替大量文件,你可能想要考虑一个数据库(多个记录) - 如果你运行的数据有一些可识别的话,你甚至可能在没有实际序列化的情况下逃脱"架构"到它.