diff options
Diffstat (limited to '')
-rw-r--r-- | Tools/NoiseSpeedTest/NoiseSpeedTest.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/Tools/NoiseSpeedTest/NoiseSpeedTest.cpp b/Tools/NoiseSpeedTest/NoiseSpeedTest.cpp new file mode 100644 index 000000000..6857b1a27 --- /dev/null +++ b/Tools/NoiseSpeedTest/NoiseSpeedTest.cpp @@ -0,0 +1,149 @@ +// NoiseSpeedTest.cpp + +// Implements the main app entrypoint + +/* +This program compares the performance of the highly-optimized noise implementation in Cuberite, and the Simplex noise. +Since the Simplex noise is not yet implemented in Cuberite, an own implementation is provided. +Also, the performance difference between using a float and double as datatype is measured, by using a templatized Simplex noise. + +The testing is done on a usage of the generator that is typical for the Cuberite's terrain generator: generate a 3D array of numbers with +not much variance in the coords. The exact sizes and coord ranges were adapted from the cNoise3DComposable generator. +*/ + +#include "Globals.h" +#include "Noise/Noise.h" +#include "Noise/InterpolNoise.h" +#include "SimplexNoise.h" + + + + + +/// The sizes of the interpolated noise that are calculated: +static const int SIZE_X = 33; +static const int SIZE_Y = 5; +static const int SIZE_Z = 5; + + + + + +static void measureClassicNoise(int a_NumIterations) +{ + cInterp5DegNoise noise(1); + NOISE_DATATYPE total = 0; + auto timeStart = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < a_NumIterations; ++i) + { + NOISE_DATATYPE out[SIZE_X * SIZE_Y * SIZE_Z]; + int blockX = i * 16; + int blockZ = i * 16; + NOISE_DATATYPE startX = 0; + NOISE_DATATYPE endX = 257 / 80.0f; + NOISE_DATATYPE startY = blockX / 40.0f; + NOISE_DATATYPE endY = (blockX + 16) / 40.0f; + NOISE_DATATYPE startZ = blockZ / 40.0f; + NOISE_DATATYPE endZ = (blockZ + 16) / 40.0f; + noise.Generate3D(out, SIZE_X, SIZE_Y, SIZE_Z, startX, endX, startY, endY, startZ, endZ); + total += out[0]; // Do not let the optimizer optimize the whole calculation away + } + auto timeEnd = std::chrono::high_resolution_clock::now(); + auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeStart); + printf("Classic noise took %d milliseconds, returned total %f\n", static_cast<int>(msec.count()), total); +} + + + + + +static void measureSimplexNoiseFloat(int a_NumIterations) +{ + typedef float DATATYPE; + cSimplexNoise<DATATYPE> noise(1); + DATATYPE total = 0; + auto timeStart = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < a_NumIterations; ++i) + { + DATATYPE out[SIZE_X * SIZE_Y * SIZE_Z]; + int blockX = i * 16; + int blockZ = i * 16; + DATATYPE startX = 0; + DATATYPE endX = 257 / 80.0f; + DATATYPE startY = blockX / 40.0f; + DATATYPE endY = (blockX + 16) / 40.0f; + DATATYPE startZ = blockZ / 40.0f; + DATATYPE endZ = (blockZ + 16) / 40.0f; + noise.Generate3D(out, SIZE_X, SIZE_Y, SIZE_Z, startX, endX, startY, endY, startZ, endZ); + total += out[0]; // Do not let the optimizer optimize the whole calculation away + } + auto timeEnd = std::chrono::high_resolution_clock::now(); + auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeStart); + printf("SimplexNoise<float> took %d milliseconds, returned total %f\n", static_cast<int>(msec.count()), total); +} + + + + + +static void measureSimplexNoiseDouble(int a_NumIterations) +{ + typedef double DATATYPE; + cSimplexNoise<DATATYPE> noise(1); + DATATYPE total = 0; + auto timeStart = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < a_NumIterations; ++i) + { + DATATYPE out[SIZE_X * SIZE_Y * SIZE_Z]; + int blockX = i * 16; + int blockZ = i * 16; + DATATYPE startX = 0; + DATATYPE endX = 257 / 80.0f; + DATATYPE startY = blockX / 40.0f; + DATATYPE endY = (blockX + 16) / 40.0f; + DATATYPE startZ = blockZ / 40.0f; + DATATYPE endZ = (blockZ + 16) / 40.0f; + noise.Generate3D(out, SIZE_X, SIZE_Y, SIZE_Z, startX, endX, startY, endY, startZ, endZ); + total += out[0]; // Do not let the optimizer optimize the whole calculation away + } + auto timeEnd = std::chrono::high_resolution_clock::now(); + auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeStart); + printf("SimplexNoise<double> took %d milliseconds, returned total %f\n", static_cast<int>(msec.count()), total); +} + + + + + +int main(int argc, char ** argv) +{ + int numIterations = 10000; + if (argc > 1) + { + numIterations = std::atoi(argv[1]); + if (numIterations < 10) + { + printf("Invalid number of iterations, using 1000 instead\n"); + numIterations = 1000; + } + } + + // Perform each test twice, to account for cache-warmup: + measureClassicNoise(numIterations); + measureClassicNoise(numIterations); + measureSimplexNoiseFloat(numIterations); + measureSimplexNoiseFloat(numIterations); + measureSimplexNoiseDouble(numIterations); + measureSimplexNoiseDouble(numIterations); + + // If build on Windows using MSVC, wait for a keypress before ending: + #ifdef _MSC_VER + getchar(); + #endif + + return 0; +} + + + + |