#include "StandardPoolBuilder.h" #include #include "../../inc/tbb/parallel_sort.h" std::string StandardPoolBuilder::GetFullFileName(const std::string& fileName) const { return fileName + ".s.pool"; } std::vector StandardPoolBuilder::GetPointerSizesPerLevel(const BaseTree* tree) const { unsigned8 depth = tree->GetMaxLevel(); std::vector res(depth + 1); res[depth] = 0; // Pointers in the leafs have size 0; for (unsigned8 level = depth; level > 0; level--) { unsigned8 bytesPerPointer = res[level]; size_t requiredBytesNextLevel = 0; for (unsigned32 i = 0; i < (unsigned32)tree->GetNodeCount(); i++) { auto node = tree->GetNode(i); if (node->GetLevel() == level) requiredBytesNextLevel += GetBaseNodeSize(tree, i) + node->GetChildCount() * bytesPerPointer; } res[level - 1] = BitHelper::RoundToBytes(std::max(1, BitHelper::Log2Ceil(requiredBytesNextLevel))) / 8; } for (unsigned8 level = 0; level <= depth; level++) printf("Pointers in level %u: %u bytes\n", level, res[level]); return res; } void StandardPoolBuilder::CalculatePointerSizesPerLevel(const BaseTree* tree) { assert(tree != NULL); mPointerSizesPerLevel = GetPointerSizesPerLevel(tree); } void StandardPoolBuilder::InitBuild(const BaseTree* tree) { CalculatePointerSizesPerLevel(tree); mIsBuildingTree = true; } void StandardPoolBuilder::FinishBuild(const BaseTree* tree) { ClearVariables(); mIsBuildingTree = false; } unsigned8 StandardPoolBuilder::GetBytesPerPointer(const BaseTree* tree, const unsigned32& nodeIndex) const { const Node* node = tree->GetNode(nodeIndex); if (node->GetLevel() == 0) return 0; return mPointerSizesPerLevel[node->GetLevel() - 1]; } size_t StandardPoolBuilder::GetPoolInfoSize(const BaseTree* tree) const { assert(tree != NULL); unsigned8 depth = tree->GetMaxLevel(); return (depth + 1) * 4 // Leave some space for the level offsets (32 bits = 4 bytes per level), + (depth + 1); // Space for the size of the node pointers } std::vector StandardPoolBuilder::GetPoolInfo(const BaseTree* tree, const std::vector& nodePointers, const std::vector& nodeOrder) { //// Go through the level (in order), keeping track of the indices //for (unsigned8 level = 0; level <= depth; level++) //{ // auto levelStart = levelIndices[level]; // auto levelEnd = levelIndices[level + 1]; // levelOffsets[level] = (unsigned32)curIndex; // for (auto i = levelStart; i < levelEnd; i++) // { // Node* node = tree->GetNode(nodeOrder[i]); // nodePointers[node->GetIndex()] = curIndex - levelOffsets[level]; // assert(level == 0 || nodePointers[node->GetIndex()] < BitHelper::Exp2(bytesPerPointer[level - 1] * 8)); // Assert the index fits // curIndex += 1 + additionalBytesPerNode[level] + node->GetChildCount() * (bytesPerPointer[level] + additionalBytesPerPointer[level]); // } //} mLevelOffsets = std::vector(tree->GetMaxLevel() + 1); unsigned8 curLevel = 255; for (size_t i = 0; i < tree->GetNodeCount(); i++) { unsigned32 nodeId = nodeOrder[i]; const Node* node = tree->GetNode(nodeId); if (node->GetLevel() != curLevel) { curLevel++; mLevelOffsets[curLevel] = (unsigned32)nodePointers[nodeId]; } } std::vector res(GetPoolInfoSize(tree)); size_t curIndex = 0; // Write the level offsets for (unsigned8 level = 0; level <= tree->GetMaxLevel(); level++) { BitHelper::SplitInBytesAndMove(mLevelOffsets[level], res, curIndex); curIndex += 4; } // Write the number of bytes per pointer for (unsigned8 level = 0; level <= tree->GetMaxLevel(); level++) res[curIndex++] = mPointerSizesPerLevel[level]; return res; } std::vector StandardPoolBuilder::WrapPointer(const BaseTree* tree, const unsigned32& nodeIndex, const unsigned32& indexInPool, const unsigned32& pointer) const { const Node* node = tree->GetNode(nodeIndex); unsigned8 nodeLevel = node->GetLevel(); unsigned32 withinLevelPointer = pointer - mLevelOffsets[nodeLevel]; return BitHelper::SplitInBytes(withinLevelPointer, mPointerSizesPerLevel[nodeLevel - 1]); } void StandardPoolBuilder::ClearVariables() { mPointerSizesPerLevel.clear(); mLevelOffsets.clear(); } //void StandardPoolBuilder::OrderNodes(const BaseTree* tree, std::vector& nodeOrder) const //{ // std::vector parentCounts = tree->GetParentCounts(); // // First order on level (asc), then on number of parents (desc), so that the most used nodes have the smallest pointers // tbb::parallel_sort(nodeOrder.begin(), nodeOrder.end(), [tree, parentCounts](const unsigned32& i1, const unsigned32& i2) // { // Node* a = tree->GetNode(i1); // Node* b = tree->GetNode(i2); // if (a->GetLevel() != b->GetLevel()) return a->GetLevel() < b->GetLevel(); // if (parentCounts[i1] != parentCounts[i2]) return parentCounts[i1] > parentCounts[i2]; // // If the level and number of parents is the same, then, for consistency, order on nodeID. // return i1 < i2; // }); //}