Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';在C+;中反序列化树的最快方法是什么+; 我正在用C++实现的一个不那么小的树结构(它是内存中的Burkhard Keller Tree,100 MB)。指向每个节点的子节点的指针存储在QHash中_C++_Performance_Qt_Serialization_Tree - Fatal编程技术网

什么';在C+;中反序列化树的最快方法是什么+; 我正在用C++实现的一个不那么小的树结构(它是内存中的Burkhard Keller Tree,100 MB)。指向每个节点的子节点的指针存储在QHash中

什么';在C+;中反序列化树的最快方法是什么+; 我正在用C++实现的一个不那么小的树结构(它是内存中的Burkhard Keller Tree,100 MB)。指向每个节点的子节点的指针存储在QHash中,c++,performance,qt,serialization,tree,C++,Performance,Qt,Serialization,Tree,每个节点x有n个子节点y[1]。。。y[n],子节点的边用编辑距离d(x,y[i])标记,因此使用散列存储节点是一个明显的解决方案 class Node { int value; QHash<int, Node*> children; /* ... */ }; 因此,造成延迟的肯定不是我的新调用,而是每个节点上QHash对象的重建。这基本上是通过以下方式完成的: QDataStream in(&infile); in >> node.

每个节点x有n个子节点y[1]。。。y[n],子节点的边用编辑距离d(x,y[i])标记,因此使用散列存储节点是一个明显的解决方案

class Node {
    int value;
    QHash<int, Node*> children;
    /* ... */
};
因此,造成延迟的肯定不是我的新调用,而是每个节点上QHash对象的重建。这基本上是通过以下方式完成的:

 QDataStream in(&infile);
 in >> node.hash;

我必须深入QHash看看引擎盖下面发生了什么吗?我认为最好的解决方案是一个哈希对象,它可以通过一次读写操作进行序列化,而无需重建内部数据结构。

我强烈建议使用。它应该与您正在使用的解决方案配合使用。

绝对最快的序列化/反序列化方法是如您所说将一块连续内存写入磁盘。如果您更改了树结构来创建它(可能使用自定义分配例程),这将非常容易

不幸的是,我不太熟悉QHash,但从它的外观来看,它看起来像一个哈希表,而不是一棵树。我误解你了吗?您正在使用此映射重复节点吗


我会使用一个分析器(我曾经使用Quantify,现在称为Rational PurifyPlus,但是有很多)来查找您使用时间的位置,但我猜它要么是多个内存分配而不是单个分配,要么是多个读取而不是单个读取。要解决这两个问题,您需要事先知道(因为您存储了它)需要多少节点,然后写入/读取一个长度正确的节点数组,其中每个指针都是数组的索引,而不是内存中的指针。

另一个解决方案是使用您自己的内存分配器,它将使用一个连续的内存空间。然后您就可以按原样转储内存并重新加载。它对平台(即big-endian/little-endian,32位/64位)敏感。

正如您所说,为对象分配新数据可能会很慢。这可以通过分配对象池,然后使用预先分配的对象来改进,直到池耗尽。您甚至可以通过重载相关类的new/delete操作符来在后台实现这一点。

首先,对应用程序进行分析,以便了解需要花费的时间-将怀疑建立在新的基础上,因为您已经在某个地方读到它可能很慢,或者通过树进行迭代是不够的

有可能是IO操作造成的-可能是您的文件格式不正确/效率低下

也许你只是在某个地方有缺陷

或者可能在某个地方有一个二次循环,你不记得是什么导致了这些问题?:)


在您的情况下,衡量真正需要时间的是什么,然后解决问题-这将为您节省大量时间,并避免在找到真正原因之前破坏您的设计/代码来修复不存在的性能问题。

使用重载运算符new()和delete()分配您自己的内存是一个低成本的选项(开发时间)。 但是,这只影响内存分配时间,而不影响Ctor时间。
您的里程数可能有所不同,但可能值得一试。

我将进一步阐述我的评论:

由于您的分析表明QHash序列化花费的时间最多,因此我相信用QList替换QHash将在反序列化速度方面产生显著的改进

QHash序列化只输出键/值对,但反序列化构造了一个hash数据结构


即使您说您需要快速子查找,我还是建议您尝试使用QList>替换QHash作为测试。如果每个节点的子节点不多(比如少于30个),那么即使使用QList,查找速度也应该足够快。如果您发现QList不够快,您仍然可以将其用于(反)序列化,然后在加载树后将其转换为哈希。

另一种方法是序列化指针并在加载时还原它们。我的意思是:

序列化:

nodeList = collectAllNodes();

for n in nodelist:
 write ( &n )
 writeNode( n ) //with pointers as-they-are.
//read all nodes into a list.
while ( ! eof(f))
    read( prevNodeAddress)
    readNode( node )
    fixMap[prevNodeAddress] = &node;
    nodeList.append(node);

//fix pointers to new values.
for n in nodeList:
    for child in n.children:
        child->node = fixMap[child->node]
反序列化:

nodeList = collectAllNodes();

for n in nodelist:
 write ( &n )
 writeNode( n ) //with pointers as-they-are.
//read all nodes into a list.
while ( ! eof(f))
    read( prevNodeAddress)
    readNode( node )
    fixMap[prevNodeAddress] = &node;
    nodeList.append(node);

//fix pointers to new values.
for n in nodeList:
    for child in n.children:
        child->node = fixMap[child->node]

这样,如果您不插入或删除新节点,您可以一次性分配一个向量并使用该内存,从而减少对映射的分配(正如rpg所说,使用列表甚至向量可能更快)。

树的每个节点都有一个键和一个哈希表到其叶。每个叶都被任意数解引用。精确地说:一个节点x有n个叶子y_1。。。y_n,从x到y_i的每条边都标有从d(x,y_i)的编辑距离(参见)。-1对于这个想法:您提到了一些问题,但事实上这也是一个问题,优化级别和调试/发布敏感-更不用说将来扩展树并很好地处理迁移了。+1到偏移量:使用合适的抽象级别,这当然是可能的-例如使用迭代器,存储偏移量而不是指针。特别是对于“构建一次,永不修改”的竞技场分配器,效率极高。平台可移植性是一个问题,但它可能无法解决OP的问题。我完全同意。在进行优化之前,请始终进行配置。即使您的gues是正确的,您也会确切地知道给定优化的收益。每个节点都存储有一个重载的
I second this:Boost是一个很好的解决方案,可以自动处理所有的子/父关系。考虑到基准测试显示QHash(当前针对儿童/家长的解决方案)在大多数情况下都会被消耗掉,因此值得研究。它也可以在各种平台上使用。另一方面,我不知道Boost与QT的配合有多好。您需要快速访问特定节点y[I]吗?尝试使用QList而不是QHash,在I/O方面使用它应该更快。