Improved test for PagedVolume::Chunk performance.
This commit is contained in:
		| @@ -51,8 +51,12 @@ namespace PolyVox | |||||||
| 		Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uSideLength - 1, m_uSideLength - 1, m_uSideLength - 1); | 		Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uSideLength - 1, m_uSideLength - 1, m_uSideLength - 1); | ||||||
| 		Region reg(v3dLower, v3dUpper); | 		Region reg(v3dLower, v3dUpper); | ||||||
|  |  | ||||||
| 		// Page the data in | 		// A valid pager is normally present - this check is mostly to ease unit testing. | ||||||
| 		m_pPager->pageIn(reg, this); | 		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. | 		// We'll use this later to decide if data needs to be paged out again. | ||||||
| 		m_bDataModified = false; | 		m_bDataModified = false; | ||||||
| @@ -61,7 +65,7 @@ namespace PolyVox | |||||||
| 	template <typename VoxelType> | 	template <typename VoxelType> | ||||||
| 	PagedVolume<VoxelType>::Chunk::~Chunk() | 	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. | 			// From the coordinates of the chunk we deduce the coordinates of the contained voxels. | ||||||
| 			Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast<int32_t>(m_uSideLength); | 			Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast<int32_t>(m_uSideLength); | ||||||
|   | |||||||
| @@ -268,15 +268,15 @@ TestVolume::TestVolume() | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Note - We are reusing the FilePager for testing... watch out for conflicts with the main volume. | 	// 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); | 	m_pPagedVolumeChunk = new PagedVolume<uint32_t>::Chunk(Vector3DInt32(10000, 10000, 10000), m_uChunkSideLength, nullptr); | ||||||
| 	int32_t i = 0; | 	std::mt19937 rng; | ||||||
| 	for (uint16_t z = 0; z < m_uChunkSideLength; z++) | 	for (uint16_t z = 0; z < m_uChunkSideLength; z++) | ||||||
| 	{ | 	{ | ||||||
| 		for (uint16_t y = 0; y < m_uChunkSideLength; y++) | 		for (uint16_t y = 0; y < m_uChunkSideLength; y++) | ||||||
| 		{ | 		{ | ||||||
| 			for (uint16_t x = 0; x < m_uChunkSideLength; x++) | 			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)); | 	QCOMPARE(result, static_cast<int32_t>(-993539594)); | ||||||
| } | } | ||||||
|  |  | ||||||
| int32_t TestVolume::testPagedVolumeChunkAccess(uint32_t locality) | int32_t TestVolume::testPagedVolumeChunkAccess(uint16_t localityMask) | ||||||
| { | { | ||||||
| 	std::mt19937 rng; | 	std::mt19937 rng; | ||||||
| 	int32_t result = 0; | 	int32_t sum = 0; | ||||||
| 	uint16_t x = rng() % m_uChunkSideLength; | 	uint16_t x = 0; | ||||||
| 	uint16_t y = rng() % m_uChunkSideLength; | 	uint16_t y = 0; | ||||||
| 	uint16_t z = rng() % m_uChunkSideLength; | 	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; | 		// Random number generation is relatively slow compared to retireving a voxel, so if we are not | ||||||
| 		uint16_t yOffset = rng() % locality; | 		// careful the process of choosing which voxel to get can become slower than actually getting it. | ||||||
| 		uint16_t zOffset = rng() % locality; | 		// Therefore we use the same random number multiple times by getting different bits from it. | ||||||
| 		x += xOffset; | 		uint32_t rand = rng(); | ||||||
| 		y += yOffset; |  | ||||||
| 		z += zOffset; | 		// We have 32 random bits and we make 27 (3*9) calls to getVoxel(). This means we | ||||||
| 		x %= m_uChunkSideLength; | 		// stop using the lower bits before they all get set to zero from the right-shifting. | ||||||
| 		y %= m_uChunkSideLength; | 		// An odd number means we have an imbalance between the number of times we go forward vs.  | ||||||
| 		z %= m_uChunkSideLength; | 		// backwards, so overall we will drift around the volume even if locality is constrained. | ||||||
| 		int32_t voxel = m_pPagedVolumeChunk->getVoxel(x, y, z); | 		for (uint32_t i = 0; i < 3; i++) | ||||||
| 		result = cantorTupleFunction(result, voxel); | 		{ | ||||||
|  | 			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() | void TestVolume::testPagedVolumeChunkLocalAccess() | ||||||
| @@ -499,9 +549,9 @@ void TestVolume::testPagedVolumeChunkLocalAccess() | |||||||
| 	int32_t result = 0; | 	int32_t result = 0; | ||||||
| 	QBENCHMARK | 	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() | void TestVolume::testPagedVolumeChunkRandomAccess() | ||||||
| @@ -509,9 +559,9 @@ void TestVolume::testPagedVolumeChunkRandomAccess() | |||||||
| 	int32_t result = 0; | 	int32_t result = 0; | ||||||
| 	QBENCHMARK | 	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) | QTEST_MAIN(TestVolume) | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ private slots: | |||||||
| 	void testPagedVolumeChunkRandomAccess(); | 	void testPagedVolumeChunkRandomAccess(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	int32_t testPagedVolumeChunkAccess(uint32_t locality); | 	int32_t testPagedVolumeChunkAccess(uint16_t localityMask); | ||||||
|  |  | ||||||
| 	static const uint16_t m_uChunkSideLength = 32; | 	static const uint16_t m_uChunkSideLength = 32; | ||||||
|  |  | ||||||
| @@ -73,7 +73,7 @@ private: | |||||||
| 	PolyVox::RawVolume<int32_t>* m_pRawVolume; | 	PolyVox::RawVolume<int32_t>* m_pRawVolume; | ||||||
| 	PolyVox::PagedVolume<int32_t>* m_pPagedVolume; | 	PolyVox::PagedVolume<int32_t>* m_pPagedVolume; | ||||||
|  |  | ||||||
| 	PolyVox::PagedVolume<int32_t>::Chunk* m_pPagedVolumeChunk; | 	PolyVox::PagedVolume<uint32_t>::Chunk* m_pPagedVolumeChunk; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user