The idea of a 'setTargetMemoryLimitInBytes' function was not really working out. It was too comp-lex and not really clear what the ideal size would be. I think user code needs to call setMaxNumberOfBlocksInMemory() and setMaxNumberOfUncompressedBlocks() directly, if they see from profiling toat too much camressing or paging is taking place.
This commit is contained in:
parent
7cd115b33d
commit
7146b5ecdb
@ -153,9 +153,8 @@ int main(int argc, char *argv[])
|
||||
RLECompressor<MaterialDensityPair44, uint16_t>* compressor = new RLECompressor<MaterialDensityPair44, uint16_t>();
|
||||
PerlinNoisePager* pager = new PerlinNoisePager();
|
||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion, compressor, pager, 256);
|
||||
//volData.setMaxNumberOfBlocksInMemory(4096);
|
||||
//volData.setMaxNumberOfUncompressedBlocks(64);
|
||||
volData.setTargetMemoryLimitInBytes(128 * 1024 * 1024);
|
||||
volData.setMaxNumberOfBlocksInMemory(4096);
|
||||
volData.setMaxNumberOfUncompressedBlocks(64);
|
||||
|
||||
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
||||
//createSphereInVolume(volData, 30);
|
||||
|
@ -263,10 +263,10 @@ namespace PolyVox
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
void setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes);
|
||||
|
||||
/// Sets the number of blocks for which uncompressed data is stored
|
||||
void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
|
||||
/// Sets the number of blocks which can be in memory before the paging system starts unloading them
|
||||
void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
@ -346,8 +346,7 @@ namespace PolyVox
|
||||
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||
mutable UncompressedBlock<VoxelType>* m_pLastAccessedBlock;
|
||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||
|
||||
uint32_t m_uTargetMemoryLimitInBytes;
|
||||
uint32_t m_uMaxNumberOfBlocksInMemory;
|
||||
|
||||
// The size of the volume
|
||||
Region m_regValidRegionInBlocks;
|
||||
|
@ -243,62 +243,6 @@ namespace PolyVox
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes)
|
||||
{
|
||||
// Set the limit, and then work out how big the uncompressed cache should be.
|
||||
m_uTargetMemoryLimitInBytes = uTargetMemoryLimitInBytes;
|
||||
|
||||
// The size of a single uncompressed block of data.
|
||||
uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
|
||||
// When deciding how to split the memory between compressed and uncompressed blocks it is useful to know the dimensions of the
|
||||
// volume in blocks. After sorting, the array below will hold the smallest dimension in [0] and the largest dimension in [2].
|
||||
const uint32_t uNoOfDimensions = 3;
|
||||
uint32_t uSortedDimensionsInBlocks[uNoOfDimensions];
|
||||
uSortedDimensionsInBlocks[0] = (getEnclosingRegion().getWidthInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||
uSortedDimensionsInBlocks[1] = (getEnclosingRegion().getHeightInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||
uSortedDimensionsInBlocks[2] = (getEnclosingRegion().getDepthInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||
std::sort(uSortedDimensionsInBlocks, uSortedDimensionsInBlocks + uNoOfDimensions);
|
||||
|
||||
const uint32_t uLongestEdgeInBlocks = uSortedDimensionsInBlocks[2];
|
||||
const uint32_t uLargestFaceSizeInBlocks = uSortedDimensionsInBlocks[1] * uSortedDimensionsInBlocks[2];
|
||||
|
||||
// In the ideal situation we will be able to keep an entire face of blocks decompressed in the cache, and still have significant memory
|
||||
// left for storing a large number of compressed block. Failing this, we would at least like to be able to keep enough blocks decompressed
|
||||
// to iterate over the longest edge. Otherwise we will find that excessive compression and decompresion occurs. In both cases we multiply
|
||||
// by an extra factor make sure there is space for storing some compressed data as well.
|
||||
const uint32_t uFactor = 2; // Just to make sure we leave some space for compressed data as well
|
||||
const uint32_t uIdealMemoryTarget = uLargestFaceSizeInBlocks * uUncompressedBlockSizeInBytes * uFactor;
|
||||
const uint32_t uAcceptableMemoryTarget = uLongestEdgeInBlocks * uUncompressedBlockSizeInBytes * uFactor;
|
||||
|
||||
if(uTargetMemoryLimitInBytes >= uIdealMemoryTarget)
|
||||
{
|
||||
logDebug() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) is plenty for a volume of this size)";
|
||||
|
||||
// The added value below is just some extra 'grace' space.
|
||||
setMaxNumberOfUncompressedBlocks(uLargestFaceSizeInBlocks + uSortedDimensionsInBlocks[1]);
|
||||
}
|
||||
else if(uTargetMemoryLimitInBytes >= uAcceptableMemoryTarget)
|
||||
{
|
||||
logDebug() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) should be acceptable for a volume of this size)";
|
||||
|
||||
// Let's (arbitrarily) use 1/4 of the available memory for the cache, while making sure that it is as long as the longest side.
|
||||
uint32_t uMaxFittableUncompressedBlocks = uTargetMemoryLimitInBytes / uUncompressedBlockSizeInBytes;
|
||||
setMaxNumberOfUncompressedBlocks((std::max)(uMaxFittableUncompressedBlocks / 4, uLongestEdgeInBlocks));
|
||||
}
|
||||
else
|
||||
{
|
||||
logWarning() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) is too low for a volume of this size)";
|
||||
logWarning() << "Excessive block thrashing may occur and the target memory limit may not be honored";
|
||||
|
||||
// We still have to do something. Let's still use 1/4 of the memory for the cache, but also set a minimum size.
|
||||
const uint32_t uMinNoOfUncompressedBlocks = 8; // Chosen because it just feels about right.
|
||||
uint32_t uMaxFittableUncompressedBlocks = uTargetMemoryLimitInBytes / uUncompressedBlockSizeInBytes;
|
||||
setMaxNumberOfUncompressedBlocks((std::max)(uMaxFittableUncompressedBlocks / 4, uMinNoOfUncompressedBlocks));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the size of the block cache will increase memory but may improve performance.
|
||||
/// You may want to set this to a large value (e.g. 1024) when you are first loading your
|
||||
@ -317,6 +261,21 @@ namespace PolyVox
|
||||
<< ", which is " << m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes << " bytes";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the number of blocks in memory causes less paging to occur
|
||||
/// \param uMaxNumberOfBlocksInMemory The number of blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
flushAll();
|
||||
}
|
||||
|
||||
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
|
@ -281,9 +281,8 @@ TestVolume::TestVolume()
|
||||
m_pSimpleVolume = new SimpleVolume<int32_t>(region);
|
||||
m_pLargeVolume = new LargeVolume<int32_t>(region, m_pCompressor, m_pFilePager, 32);
|
||||
|
||||
//m_pLargeVolume->setMaxNumberOfBlocksInMemory(32);
|
||||
//m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16);
|
||||
m_pLargeVolume->setTargetMemoryLimitInBytes(4 * 1024 * 1024);
|
||||
m_pLargeVolume->setMaxNumberOfBlocksInMemory(32);
|
||||
m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16);
|
||||
|
||||
//Fill the volume with some data
|
||||
for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
|
||||
|
Loading…
x
Reference in New Issue
Block a user