135 lines
4.9 KiB
C++
135 lines
4.9 KiB
C++
#include "StandardPoolBuilder.h"
|
|
#include <algorithm>
|
|
#include "../../inc/tbb/parallel_sort.h"
|
|
|
|
std::string StandardPoolBuilder::GetFullFileName(const std::string& fileName) const
|
|
{
|
|
return fileName + ".s.pool";
|
|
}
|
|
|
|
std::vector<unsigned8> StandardPoolBuilder::GetPointerSizesPerLevel(const BaseTree* tree) const
|
|
{
|
|
unsigned8 depth = tree->GetMaxLevel();
|
|
std::vector<unsigned8> 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<unsigned8>(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<unsigned8> StandardPoolBuilder::GetPoolInfo(const BaseTree* tree, const std::vector<size_t>& nodePointers, const std::vector<unsigned32>& 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<unsigned32>(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<unsigned8> 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<unsigned8> 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<unsigned32>& nodeOrder) const
|
|
//{
|
|
// std::vector<size_t> 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;
|
|
// });
|
|
//}
|