Improved test for PagedVolume::Chunk performance.

This commit is contained in:
David Williams 2015-03-26 23:45:01 +01:00
parent 1d24b189ca
commit 322bedc009
3 changed files with 84 additions and 30 deletions

View File

@ -51,8 +51,12 @@ namespace PolyVox
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uSideLength - 1, m_uSideLength - 1, m_uSideLength - 1);
Region reg(v3dLower, v3dUpper);
// Page the data in
m_pPager->pageIn(reg, this);
// A valid pager is normally present - this check is mostly to ease unit testing.
if (m_pPager)
{
// Page the data in
m_pPager->pageIn(reg, this);
}
// We'll use this later to decide if data needs to be paged out again.
m_bDataModified = false;
@ -61,7 +65,7 @@ namespace PolyVox
template <typename VoxelType>
PagedVolume<VoxelType>::Chunk::~Chunk()
{
if (m_bDataModified)
if (m_bDataModified && m_pPager)
{
// From the coordinates of the chunk we deduce the coordinates of the contained voxels.
Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast<int32_t>(m_uSideLength);

View File

@ -268,15 +268,15 @@ TestVolume::TestVolume()
}
// Note - We are reusing the FilePager for testing... watch out for conflicts with the main volume.
m_pPagedVolumeChunk = new PagedVolume<int32_t>::Chunk(Vector3DInt32(10000, 10000, 10000), m_uChunkSideLength, m_pFilePager);
int32_t i = 0;
m_pPagedVolumeChunk = new PagedVolume<uint32_t>::Chunk(Vector3DInt32(10000, 10000, 10000), m_uChunkSideLength, nullptr);
std::mt19937 rng;
for (uint16_t z = 0; z < m_uChunkSideLength; z++)
{
for (uint16_t y = 0; y < m_uChunkSideLength; y++)
{
for (uint16_t x = 0; x < m_uChunkSideLength; x++)
{
m_pPagedVolumeChunk->setVoxel(x, y, z, ++i);
m_pPagedVolumeChunk->setVoxel(x, y, z, static_cast<uint32_t>(rng()));
}
}
}
@ -468,30 +468,80 @@ void TestVolume::testPagedVolumeSamplersWithExternalBackwards()
QCOMPARE(result, static_cast<int32_t>(-993539594));
}
int32_t TestVolume::testPagedVolumeChunkAccess(uint32_t locality)
int32_t TestVolume::testPagedVolumeChunkAccess(uint16_t localityMask)
{
std::mt19937 rng;
int32_t result = 0;
uint16_t x = rng() % m_uChunkSideLength;
uint16_t y = rng() % m_uChunkSideLength;
uint16_t z = rng() % m_uChunkSideLength;
int32_t sum = 0;
uint16_t x = 0;
uint16_t y = 0;
uint16_t z = 0;
for (uint32_t ct = 0; ct < 1000000; ct++)
// Used to constrain the range, as '&=m_uChunkSideLengthMask' should be faster than '%=m_uChunkSideLength'.
uint16_t m_uChunkSideLengthMask = m_uChunkSideLength - 1;
for (int32_t ct = 0; ct < 1000000; ct++)
{
uint16_t xOffset = rng() % locality;
uint16_t yOffset = rng() % locality;
uint16_t zOffset = rng() % locality;
x += xOffset;
y += yOffset;
z += zOffset;
x %= m_uChunkSideLength;
y %= m_uChunkSideLength;
z %= m_uChunkSideLength;
int32_t voxel = m_pPagedVolumeChunk->getVoxel(x, y, z);
result = cantorTupleFunction(result, voxel);
// Random number generation is relatively slow compared to retireving a voxel, so if we are not
// careful the process of choosing which voxel to get can become slower than actually getting it.
// Therefore we use the same random number multiple times by getting different bits from it.
uint32_t rand = rng();
// We have 32 random bits and we make 27 (3*9) calls to getVoxel(). This means we
// stop using the lower bits before they all get set to zero from the right-shifting.
// An odd number means we have an imbalance between the number of times we go forward vs.
// backwards, so overall we will drift around the volume even if locality is constrained.
for (uint32_t i = 0; i < 3; i++)
{
x += rand & localityMask; // Move x forwardsby a small amount, limited by localityMask.
x &= m_uChunkSideLengthMask; // Ensure it is within the valid range.
sum += m_pPagedVolumeChunk->getVoxel(x, y, z); // Get the voxel value and use it.
rand >>= 1; // Shift the bits so we use different ones next time.
y -= rand & localityMask; // This one (and some others) are negative so sometimes we go backwards.
y &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
z += rand & localityMask;
z &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
x -= rand & localityMask;
x &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
y += rand & localityMask;
y &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
z -= rand & localityMask;
z &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
x += rand & localityMask;
x &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
y -= rand & localityMask;
y &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
z += rand & localityMask;
z &= m_uChunkSideLengthMask;
sum += m_pPagedVolumeChunk->getVoxel(x, y, z);
rand >>= 1;
}
}
return result;
// It's important to use the voxel values, otherwise
// the compiler optimizes out the calls to getVoxel().
return sum;
}
void TestVolume::testPagedVolumeChunkLocalAccess()
@ -499,9 +549,9 @@ void TestVolume::testPagedVolumeChunkLocalAccess()
int32_t result = 0;
QBENCHMARK
{
result = testPagedVolumeChunkAccess(3); // Small value for good locality
result = testPagedVolumeChunkAccess(0x0003); // Small value for good locality
}
QCOMPARE(result, static_cast<int32_t>(145244783));
QCOMPARE(result, static_cast<int32_t>(1856742828));
}
void TestVolume::testPagedVolumeChunkRandomAccess()
@ -509,9 +559,9 @@ void TestVolume::testPagedVolumeChunkRandomAccess()
int32_t result = 0;
QBENCHMARK
{
result = testPagedVolumeChunkAccess(1000000); // Large value for poor locality (random access)
result = testPagedVolumeChunkAccess(0xFFFF); // Large value for poor locality (random access)
}
QCOMPARE(result, static_cast<int32_t>(-254578110));
QCOMPARE(result, static_cast<int32_t>(1550197176));
}
QTEST_MAIN(TestVolume)

View File

@ -61,7 +61,7 @@ private slots:
void testPagedVolumeChunkRandomAccess();
private:
int32_t testPagedVolumeChunkAccess(uint32_t locality);
int32_t testPagedVolumeChunkAccess(uint16_t localityMask);
static const uint16_t m_uChunkSideLength = 32;
@ -73,7 +73,7 @@ private:
PolyVox::RawVolume<int32_t>* m_pRawVolume;
PolyVox::PagedVolume<int32_t>* m_pPagedVolume;
PolyVox::PagedVolume<int32_t>::Chunk* m_pPagedVolumeChunk;
PolyVox::PagedVolume<uint32_t>::Chunk* m_pPagedVolumeChunk;
};
#endif