簡體   English   中英

減少內存分配C ++

[英]Decrease memory allocations C++

我遇到了一個麻煩,想出一個好的策略來減少以下問題的內存分配:

我正在建造一棵樹。 開始時,我只有包含一些數據的根(索引的列表( std::vector ))。 我分為兩個部分,其中一部分索引轉到左孩子,另一部分轉到右邊。 我不知道左/右會有多少。 一旦完成了根處理,就不再需要為其存儲索引了。 實際上,我只對那些葉子感興趣。 此外,可以在每次拆分時添加其他數據! 因此,如果根有20個元素,則分割后左邊的可能有12個元素,右邊的有10個元素。

在每個節點中,我保留一個std::vector ,其中包含這些索引。 當我添加元素時,我push_back()導致了很多內存分配的元素。

保持指數的好策略是什么?

這個問題與SBVH數據結構的生成有關。

碼:

struct Node {
     std::vector<unsigned> indices_;
     // ... some other stuff here
}
void partition(Node* node) {
    Node* left = new Node();
    Node* right = new Node();
    float axis = findSplitPosition(node);

    for(size_t i = 0; i < node->indices_.size(); ++i) {
        if (index is strictly left on axis) {
            left->indices_.push_back(node->indices_[i]);
        } else if(index is strictly right on axis) {
            right->indices_.push_back(node->indices_[i]);
        } else {
            // it intersects the axis -> add to left and right
            left->indices_.push_back(node->indices_[i]);
            right->indices_.push_back(node->indices_[i]);
        }
    }

    // root indices no longer needed
    node->indices_.clear();

}

如果每個節點必須自己維護一個動態列表,則可以在調用所有push_back()之前使用std::vector::reserve()

但是,如果在設置根節點后確定了整個長度,並且初始向量保持不變,然后只是在每個節點之間“拆分”,則節點本身可以​​簡單地將指針指向初始向量內的數據,從而消除了圍繞該數據結構的幾乎所有分配。

基本上,如果您不能基於某些啟發式reserve向量, 則將成為Schlemiel算法的犧牲品(盡管版本更溫和,因為幾何增長確保n個連續插入的時間復雜度為O(n)而不是O(n ^ 2))。

但是,如果首先瀏覽該節點的索引並記錄給定的索引是應到達左側子節點,右側子節點還是同時到達這兩個節點,則可以避免分配數量恆定的情況。 還要跟蹤左/右子節點的索引計數:

struct Foo {
    bool goesIntoLeft;
    bool goesIntoRight;
};

std::vector<Foo> foo;
foo.reserve(node->_indices.size());
int leftCount = 0;
int rightCount = 0;
for (auto i = 0; i < node->_indices.size(); ++i) {
    if (index goes into left) {
        foo.push_back({ true, false });
        ++leftCount;
    } else if (index goes into right) {
        foo.push_back({ false, true });
        ++rightCount;
    } else { // goes into both
        foo.push_back({ true, true });
        ++leftCount;
        ++rightCount;
    }
}

std::vector<Node> leftNodes;
leftNodes.reserve(leftCount);
std::vector<Node> rightNodes;
rightNodes.reserve(rightCount);

for (auto i = 0; i < node->_indices.size(); ++i) {
    if (foo[i].goesIntoLeft) leftNodes.push_back(nodes._indices[i]);
    if (foo[i].goesIntoRight) rightNodes.push_back(nodes._indices[i]);
}

這樣,您僅執行3個分配,即fooleftNodesrightNodes 盡管您必須兩次遍歷索引,但是繁重的工作(幾何計算)僅在第一個循環中完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM