summaryrefslogtreecommitdiffstats
path: root/Tools/NoiseSpeedTest/NoiseSpeedTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/NoiseSpeedTest/NoiseSpeedTest.cpp')
-rw-r--r--Tools/NoiseSpeedTest/NoiseSpeedTest.cpp149
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;
+}
+
+
+
+