表示转换层次结构的有效结构


9

谁能建议一种内存有效的方式来表示矩阵树,例如在层次模型中?

我特别热衷于保留数据局部性,并且我怀疑数组结构(矩阵和矩阵的索引)类型的方法可能合适。

与许多链矩阵计算一样,此结构可能会在内存中被复制很多,因此具有连续存储将是一大好处。

Answers:


6

树状排列听起来对我来说是一个胜利。只需对层次结构进行深度优先遍历并填写数组即可;在递归中倒退时,您可以使用对子项的绝对索引或仅对我的增量来更新父项,而子项也可以使用任何一种方式存储父项索引。实际上,如果使用相对偏移量,则无需携带根地址。我想结构可能看起来像

struct Transform
{
   Matrix m; // whatever you like
   int parent;   // index or offset, you choose!
   int sibling;
   int firstchild;
};

...因此,由于您无法(轻松地)拥有可变大小的结构,因此您还需要节点也知道如何到达同级。尽管我猜想如果您使用字节偏移量而不是转换偏移量,则每个转换可能具有可变数量的子代:

struct Transform
{
   Matrix m; // whatever you like
   int parent;  // negative byte offest
   int numchildren;
   int child[0]; // can't remember if you put a 0 there or leave it empty;
                 // but it's an array of positive byte offsets
};

...那么您只需要确保将正确的连续变换放在正确的位置即可。

这是使用嵌入式子“指针”构建完全独立的树的方法。

int BuildTransforms(Entity* e, OutputStream& os, int parentLocation)
{
    int currentLocation = os.Tell();

    os.Write(e->localMatrix);
    os.Write(parentLocation);
    int numChildren = e->GetNumChildren();
    os.Write(numChildren);

    int childArray = os.Tell();
    os.Skip(numChildren * sizeof(int));
    os.AlignAsNecessary();  // if you need to align transforms

    childLocation = os.Tell();
    for (int i = 0; i < numChildren; ++i) {
        os.Seek(childArray + (i * sizeof(int)));
        os.Write(childLocation);
        os.Seek(childLocation);
        childLocation = BuildTransforms(e->GetChild(i), os, currentLocation);
    }

    return os.Tell();
}

void BuildTransforms(Entity* root)
{
    OutputStream os;
    BuildTransforms(root, os, -1, 0);
}

(如果要存储相对位置,只需- currentLocation在两个“位置”中添加内容即可。)


如果我们使用的是C ++,则需要为子数组指定大小,或者在运行时使用内存分配创建它。
tenpn

官方批准的C99方法是将数组大小规格保留为空。

@ tenpn-这个想法是您有一个专用的缓冲区。关键是要避免额外的分配。您无法指定数组大小,因为您不知道数组的大小。写入num个子级后,您将写入子级数组,但是在子级数组结束后,下一个转换开始。(这就是为什么您需要为此结构使用字节偏移量而不是索引的原因;您不知道每个条目有多大,但是遍历仍然很有效并且是自包含的,因此可以作为一个单元移动。)
破折号-tom-bang 2010年

1
这称为“结构黑客”。另请参阅:notifyit.com/guides/content.aspx?g=cplusplus&seqNum=288
Neverender

1
@tenpn Aka可变长度结构。如果使用得当,它们可使堆分配的数量减半。

1

索引矩阵数组可能是最直接,最有效的内存存储方法。

一串转换可以作为一系列指向矩阵数组的指针或整数或其他小结构保存在LIFO中。这将有助于防止存储冗余矩阵,并将数据存储代码与数据访问者代码分开。

最终,您只需从LIFO推送和弹出索引值即可存储或播放转换链。

如果矩阵结构还可以包含转换类型...旋转,平移等,则还可以节省一点内存。否则,该类型将需要与索引一起存储,从而导致更多的重复。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.