我有一个非常大的 ROOT(二进制)格式的数据集,其中包含序列化的 std::vector 对象。每个长度为 N 的向量本质上表示 N 个逻辑对象集合的一个数据成员(这里,N 可能随文件中的每个条目而变化)。例如,对于文件中的每个条目,我都会读取以下对象:
std::vector<float> foo_a;
std::vector<float> foo_b;
std::vector<int> foo_c;
从逻辑上讲,这些平行场代表一个对象。我希望能够处理数据,就好像我有这个:
struct Foo {
float a;
float b;
int c;
};
std::vector<Foo> my_foos;
因此,例如,如果我想从列表中删除某个“Foo”,或者将其转换到位等,我不想跟踪它的所有并行数据成员来进行更改。
我通过 Python 访问序列化对象,使用一个库,该库简单地为我请求的每个条目传递 Python 化的 std::vector 对象。从技术上讲,相同的向量在整个文件访问过程中都存在于内存中;它们被清除并重新填充每个条目的新数据。这是我目前如何物化的草图:
class Dummy:
def __init__(self): pass
def get_objects(list_of_field_names, list_of_parallel_vectors):
names_and_vectors = zip(list_of_field_names, list_of_parallel_vectors)
n = len(list_of_parallel_vectors[0])
for i in xrange(n):
obj = Dummy()
obj_members = [(field_name, vector.at(i))
for field_name, vector in names_and_vectors]
obj.__dict__.update(obj_members)
yield obj
# ...
# get the std::vectors from file:
foo_a, foo_b, foo_c = magic()
# retrieve my python list of Foo objects:
objects_to_process = get_objects( ('a','b','c'), (foo_a, foo_b, foo_c) )
# now I can access logical data in the parallel vectors as a python object:
for obj in objects_to_process:
print (obj.a + obj.b) / obj.c
分析后,我发现对象创建和数据从向量复制到 python 对象的所有开销都是处理时间的重要瓶颈。有没有更有效的方法来达到同样的效果?
欢迎就优化的风险或更明智的方法给这只猫剥皮的原则性和明智的建议,但请记住:1)数据集很大(高达 100 TB);有数百万个条目和数千个不同长度的并行向量(对应于数十个逻辑对象)。2)我对输入数据格式没有任何控制权。