From 506e4df0c26fcca2d3b9dbaa6c918fbbc46e07bc Mon Sep 17 00:00:00 2001 From: attcs Date: Tue, 21 Jan 2025 23:44:09 +0100 Subject: [PATCH] Box benchmarks --- benchmarks/automatic/main.cpp | 447 +++++++++++++++++++++++++++---- benchmarks/manual/benchmarks.cpp | 78 +----- benchmarks/manual/generators.h | 80 +++++- 3 files changed, 481 insertions(+), 124 deletions(-) diff --git a/benchmarks/automatic/main.cpp b/benchmarks/automatic/main.cpp index 4073abc..8aa3fc2 100644 --- a/benchmarks/automatic/main.cpp +++ b/benchmarks/automatic/main.cpp @@ -22,12 +22,12 @@ namespace void GetNodeID(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; - constexpr depth_t depth = 3; + constexpr depth_t depth = 5; size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - const auto tree = TreePointND(points, depth); + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); using NodeID = typename TreePointND::MortonNodeID; std::vector entityIDs(entityNo); @@ -45,14 +45,15 @@ namespace static void GetDepthID(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; - constexpr depth_t depth = 3; + constexpr depth_t depth = 5; size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - const auto tree = TreePointND(points, depth); + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); + using NodeID = typename TreePointND::MortonNodeID; - std::vector entityIDs; + auto entityIDs = std::vector{}; for (auto const& point : points) entityIDs.emplace_back(tree.GetNodeID(point)); @@ -68,23 +69,24 @@ namespace } } // namespace Base + namespace Point { - template + template void Create(benchmark::State& state) { - constexpr dim_t DIMENSION_NO = 3; - constexpr depth_t depth = 3; + constexpr depth_t depth = 5; size_t entityNo = state.range(); - - const auto points = GeneratePointsRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const points = GeneratePointsRandom(entityNo); for (auto _ : state) { - CreateTreePoint(depth, points, IS_PARALLEL_EXEC); + auto tree = TreePointND(points, depth, boxSpace, DEFAULT_MAX_ELEMENT_IN_NODES, IS_PARALLEL_EXEC); } } + static void InsertToLeaf(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -92,11 +94,9 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - auto boxSpace = BoundingBoxND{}; - boxSpace.Max.fill(rMax); + auto const points = GeneratePointsRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); - using NodeID = typename TreePointND::MortonNodeID; for (auto _ : state) { auto tree = TreePointND(); @@ -111,6 +111,7 @@ namespace } } + static void InsertWithRebalancing(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -118,9 +119,8 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - auto boxSpace = BoundingBoxND{}; - boxSpace.Max.fill(rMax); + auto const points = GeneratePointsRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); for (auto _ : state) { @@ -136,6 +136,7 @@ namespace } } + static void InsertUnique(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -143,9 +144,8 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - auto boxSpace = BoundingBoxND{}; - boxSpace.Max.fill(rMax); + auto const points = GeneratePointsRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); for (auto _ : state) { @@ -163,7 +163,7 @@ namespace } } - + static void Update(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -171,8 +171,8 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo * 10); - const auto updatePoints = GeneratePointsRandom(entityNo); + auto const points = GeneratePointsRandom(entityNo * 10); + auto const updatePoints = GeneratePointsRandom(entityNo); auto tree = TreePointND(points, depth); for (auto _ : state) @@ -182,8 +182,50 @@ namespace tree.Update(entityID, points[entityID], updatePoints[entityID], points); } } + SetIterationNo(state, entityNo); + } + + + static void Contains(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); + + size_t entityID = 0; + for (auto _ : state) + { + tree.Contains(points[entityID % entityNo], points, rMax / 1000.0); + ++entityID; + } + } + + + static void RangeSearch(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); + constexpr size_t boxNo = 100; + auto const searchBoxes = GenerateBoxesRandom(boxNo); + + size_t entityID = 0; + for (auto _ : state) + { + tree.RangeSearch(searchBoxes[entityID % boxNo], points); + ++entityID; + } } + static void GetNearestNeighbors(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -191,20 +233,21 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - const auto tree = TreePointND(points, depth); + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); - const auto searchPoints = GeneratePointsRandom(std::max(20, entityNo / 100)); - const auto pointNo = searchPoints.size(); + auto const searchPoints = GeneratePointsRandom(std::max(20, entityNo / 100)); + auto const pointNo = searchPoints.size(); size_t pointID = 0; for (auto _ : state) { - const auto& searchPoint = searchPoints[pointID % pointNo]; + auto const& searchPoint = searchPoints[pointID % pointNo]; tree.GetNearestNeighbors(searchPoint, std::max(2, static_cast(std::floor(searchPoint[0]))), points); ++pointID; } } + static void FrustumCulling(benchmark::State& state) { constexpr dim_t DIMENSION_NO = 3; @@ -212,10 +255,10 @@ namespace size_t entityNo = state.range(); - const auto points = GeneratePointsRandom(entityNo); - const auto tree = TreePointND(points, depth); + auto const points = GeneratePointsRandom(entityNo); + auto const tree = TreePointND(points, depth); - const auto planes = std::vector{ + auto const planes = std::vector{ PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 1.0, 0.0, 0.0 } }, PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 0.0, 1.0, 0.0 } }, PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 0.0, 0.0, 1.0 } } @@ -225,22 +268,334 @@ namespace tree.FrustumCulling(planes, 0.1, points); } } + } // namespace Point + + + namespace Box + { + template + void Create(benchmark::State& state) + { + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + for (auto _ : state) + { + auto const tree = TreeBoxND(entities, depth, boxSpace, DEFAULT_MAX_ELEMENT_IN_NODES, IS_PARALLEL_EXEC); + } + } + + template + static void InsertToLeaf(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + + for (auto _ : state) + { + auto tree = TreeBoxND(); + tree.Init(boxSpace, depth); + + std::size_t entityID = 0; + for (auto const& entity : entities) + { + tree.Insert(entityID, entity, true); + ++entityID; + } + } + } + + + template + static void InsertWithRebalancing(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + + for (auto _ : state) + { + auto tree = TreeBoxND(); + tree.Init(boxSpace, depth); + + std::size_t entityID = 0; + for (auto const& entity : entities) + { + tree.InsertWithRebalancing(entityID, entity, entities); + ++entityID; + } + } + } + + + template + static void Update(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const boxSpace = CreateSearcBox(0, rMax); + auto const entities = GenerateBoxesRandom(entityNo * 10); + auto const updateEntities = GenerateBoxesRandom(entityNo); + + auto tree = TreeBoxND(entities, depth, boxSpace); + + for (auto _ : state) + { + for (size_t entityID = 0; entityID < updateEntities.size(); ++entityID) + { + tree.Update(entityID, entities[entityID], updateEntities[entityID], entities); + } + } + + SetIterationNo(state, entityNo); + } + + + template + static void PickSearch(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree = TreeBoxND(entities, depth, boxSpace); + + constexpr size_t pointNo = 100; + auto const searchPoints = GeneratePointsRandom(pointNo); + + size_t entityID = 0; + for (auto _ : state) + { + tree.PickSearch(searchPoints[entityID % pointNo], entities); + ++entityID; + } + } + + + template + static void RangeSearch(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree = TreeBoxND(entities, depth, boxSpace); + + constexpr size_t boxNo = 100; + auto const searchBoxes = GenerateBoxesRandom(boxNo); + + size_t entityID = 0; + for (auto _ : state) + { + tree.RangeSearch(searchBoxes[entityID % boxNo], entities); + ++entityID; + } + } - } // namespace + + template + static void FrustumCulling(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree = TreeBoxND(entities, depth, boxSpace); + + auto const planes = std::vector{ + PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 1.0, 0.0, 0.0 } }, + PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 0.0, 1.0, 0.0 } }, + PlaneND{ .OrigoDistance = rMax * 0.9, .Normal = { 0.0, 0.0, 1.0 } } + }; + for (auto _ : state) + { + tree.FrustumCulling(planes, 0.1, entities); + } + } + + + template + static void CollisionDetection(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree = TreeBoxND(entities, depth, boxSpace); + + for (auto _ : state) + { + tree.template CollisionDetection(entities); + } + } + + + template + static void CollisionDetection_WithOtherTree(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + auto const entities0 = GenerateBoxesRandom(entityNo); + auto const entities1 = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree0 = TreeBoxND(entities0, depth, boxSpace); + auto const tree1 = TreeBoxND(entities1, depth, boxSpace); + + for (auto _ : state) + { + TreeBoxND::CollisionDetection(tree0, entities0, tree1, entities1); + } + } + + + template + std::optional> GetNormalized(PointND const& direction) + { + auto length2 = 0.0; + for (dim_t dimensionID = 0; dimensionID < DIMENSION_NO; ++dimensionID) + { + length2 += direction[dimensionID] * direction[dimensionID]; + } + + if (length2 == 0) + { + return std::nullopt; + } + + auto normalized = direction; + auto const length = std::sqrt(length2); + for (dim_t dimensionID = 0; dimensionID < DIMENSION_NO; ++dimensionID) + { + normalized[dimensionID] = direction[dimensionID] / length; + } + + return normalized; + } + + + template + static void RayIntersectedGeneral(benchmark::State& state) + { + constexpr dim_t DIMENSION_NO = 3; + constexpr depth_t depth = 5; + + size_t entityNo = state.range(); + + auto const entities = GenerateBoxesRandom(entityNo); + auto const boxSpace = CreateSearcBox(0, rMax); + auto const tree = TreeBoxND(entities, depth, boxSpace); + + size_t constexpr rayNo = 100; + auto const rayOrigins = GeneratePointsRandom(rayNo); + auto const rayDirections = GeneratePointsRandom(rayNo); + + auto rays = std::vector>{}; + for (size_t rayID = 0; rayID < rayNo; ++rayID) + { + auto const direction = GetNormalized(rayDirections[rayID]); + if (!direction) + { + continue; + } + rays.push_back(RayND{ .Origin = rayOrigins[rayNo], .Direction = *direction }); + } + + size_t entityID = 0; + for (auto _ : state) + { + auto const [origin, direction] = rays[entityID % rayNo]; + if constexpr (IS_FIRST) + { + tree.RayIntersectedFirst(origin, direction, entities, 0); + } + else + { + tree.RayIntersectedAll(origin, direction, entities, 0); + } + ++entityID; + } + } + + template + static void RayIntersectedFirst(benchmark::State& state) + { + RayIntersectedGeneral(state); + } + + template + static void RayIntersectedAll(benchmark::State& state) + { + RayIntersectedGeneral(state); + } + } // namespace Box } // namespace Benchmarks } // namespace -BENCHMARK(Benchmarks::Base::GetNodeID)->Arg(1000); -BENCHMARK(Benchmarks::Base::GetDepthID)->Arg(1000); - -BENCHMARK(Benchmarks::Point::Create)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000); -BENCHMARK(Benchmarks::Point::Create)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000); -BENCHMARK(Benchmarks::Point::InsertToLeaf)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000); -BENCHMARK(Benchmarks::Point::InsertWithRebalancing)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000); -BENCHMARK(Benchmarks::Point::InsertUnique)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000); -BENCHMARK(Benchmarks::Point::Update)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000); -BENCHMARK(Benchmarks::Point::GetNearestNeighbors)->Arg(1000)->Arg(10000); -BENCHMARK(Benchmarks::Point::FrustumCulling)->Arg(1000)->Arg(10000); +BENCHMARK(Benchmarks::Base::GetNodeID)->Arg(1000)->Unit(benchmark::kNanosecond); +BENCHMARK(Benchmarks::Base::GetDepthID)->Arg(1000)->Unit(benchmark::kNanosecond); +BENCHMARK(Benchmarks::Point::Create<3, false>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::Create<3, true>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::InsertToLeaf)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::InsertWithRebalancing)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::InsertUnique)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::Update)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::Contains)->Arg(1000)->Arg(10000); +BENCHMARK(Benchmarks::Point::RangeSearch)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000); +BENCHMARK(Benchmarks::Point::GetNearestNeighbors)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Point::FrustumCulling)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Create<3, 0, false>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Create<3, 0, true>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Create<3, 2, false>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Create<3, 2, true>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Arg(1000000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::InsertToLeaf<0>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::InsertToLeaf<2>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::InsertWithRebalancing<0>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::InsertWithRebalancing<2>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Update<0>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::Update<2>)->Arg(10)->Arg(20)->Arg(50)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::PickSearch<0>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000); +BENCHMARK(Benchmarks::Box::PickSearch<2>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000); +BENCHMARK(Benchmarks::Box::RangeSearch<0>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000); +BENCHMARK(Benchmarks::Box::RangeSearch<2>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000); +BENCHMARK(Benchmarks::Box::FrustumCulling<0>)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::FrustumCulling<2>)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection<0, false>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection<0, true>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection<2, false>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection<2, true>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection_WithOtherTree<0>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::CollisionDetection_WithOtherTree<2>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::RayIntersectedFirst<0>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::RayIntersectedFirst<2>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::RayIntersectedAll<0>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); +BENCHMARK(Benchmarks::Box::RayIntersectedAll<2>)->Arg(100)->Arg(1000)->Arg(10000)->Arg(100000)->Unit(benchmark::kMillisecond); // Run the benchmark BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/manual/benchmarks.cpp b/benchmarks/manual/benchmarks.cpp index 708a606..4f7ebab 100644 --- a/benchmarks/manual/benchmarks.cpp +++ b/benchmarks/manual/benchmarks.cpp @@ -45,29 +45,6 @@ namespace auto constexpr degree_to_rad(double degree) { return degree / 180.0 * std::numbers::pi; } - template - static constexpr PointND CreateBoxMax(PointND const& pt, double size) - { - auto ptMax = pt; - for (size_t iDim = 0; iDim < DIMENSION_NO; ++iDim) - Adaptor::SetPointC(ptMax, static_cast(iDim), Adaptor::GetPointC(pt, static_cast(iDim)) + size); - - return ptMax; - } - - - template - static BoundingBoxND CreateSearcBox(double rBegin, double rSize) - { - auto box = BoundingBoxND{}; - for (dim_t iDim = 0; iDim < DIMENSION_NO; ++iDim) - box.Min[iDim] = rBegin; - - box.Max = CreateBoxMax(box.Min, rSize); - return box; - } - - template static vector> CreatePoints_Diagonal() { @@ -199,55 +176,6 @@ namespace return aBox; } - template - static vector> CreateBoxes_Random() - { - if (nNumber == 0) - return {}; - - auto constexpr rMax = 8.0; - auto constexpr rUnit = 1.0; - auto aBox = vector>(nNumber); - aBox[0].Max = CreateBoxMax(PointND(), rMax); - if (nNumber == 1) - return aBox; - - size_t iNumber = 1; - - // Corner points - { - for (dim_t iDim = 0; iDim < DIMENSION_NO && iNumber < nNumber; ++iDim, ++iNumber) - { - aBox[iNumber].Min[iDim] = rMax - rUnit; - aBox[iNumber].Max = CreateBoxMax(aBox[iNumber].Min, rUnit); - } - if (iNumber == nNumber) - return aBox; - - - for (dim_t iDim = 0; iDim < DIMENSION_NO; ++iDim) - aBox[iNumber].Min[iDim] = rMax - rUnit; - - aBox[iNumber].Max = CreateBoxMax(aBox[iNumber].Min, rUnit); - - ++iNumber; - } - - srand(0); - - { - for (size_t iRemain = 1; iNumber < nNumber; ++iNumber, ++iRemain) - { - auto const iNumberBox = nNumber - iNumber - 1; - for (dim_t iDim = 0; iDim < DIMENSION_NO && iNumber < nNumber; ++iDim) - aBox[iNumberBox].Min[iDim] = double(rand() % 100) * ((rMax - 1.0) / 100.0); - - aBox[iNumberBox].Max = CreateBoxMax(aBox[iNumberBox].Min, double(rand() % 100) * (1.0 * rUnit / 100.0)); - } - } - - return aBox; - } template static vector> CreateBoxes_CylindricalSemiRandom() @@ -754,7 +682,7 @@ int main() { auto const szName = string("Random placed boxes"); - auto const aPointDiag_100M = GenerateGeometry>>([&] { return CreateBoxes_Random(); }, szName, 100, report); + auto const aPointDiag_100M = GenerateGeometry>>([&] { return GenerateBoxesRandom(100 * N1M); }, szName, 100, report); auto const vTask = GenerateBoxTasks(nDepth, szName, aPointDiag_100M); RunTasks(vTask, report); } @@ -769,8 +697,8 @@ int main() // Morton vs Dynamic { auto const szName = string("Cylindrical semi-random placed points Morton vs Dynamic"); - auto const aPoint = GenerateGeometry>>([&] { return GeneratePointsRandom(); }, szName, 100, report); - auto const aBox = GenerateGeometry>>([&] { return CreateBoxes_Random(); }, szName, 100, report); + auto const aPoint = GenerateGeometry>>([&] { return GeneratePointsRandom(N1M); }, szName, 100, report); + auto const aBox = GenerateGeometry>>([&] { return GenerateBoxesRandom(N1M); }, szName, 100, report); auto const vTaskMortonP = GeneratePointTasks(nDepth, "Morton point", aPoint); auto const vTaskDynP = GeneratePointDynTasks_NonLog(nDepth, "Dynamic point", aPoint); diff --git a/benchmarks/manual/generators.h b/benchmarks/manual/generators.h index dd1fd38..b85bf25 100644 --- a/benchmarks/manual/generators.h +++ b/benchmarks/manual/generators.h @@ -8,7 +8,7 @@ using namespace OrthoTree; auto constexpr rMax = 8.0; template -static constexpr std::vector> GeneratePointsRandom(size_t pointsNo) +constexpr std::vector> GeneratePointsRandom(size_t pointsNo, int seed = 0) { auto aPoint = std::vector>(pointsNo); @@ -31,7 +31,7 @@ static constexpr std::vector> GeneratePointsRan aPoint[iNumber][iDim] = rMax; } - srand(0); + srand(seed); { for (; iNumber < pointsNo; ++iNumber) for (dim_t iDim = 0; iDim < DIMENSION_NO; ++iDim) @@ -43,7 +43,7 @@ static constexpr std::vector> GeneratePointsRan template -static size_t CreateTreePoint(depth_t depth, std::span const> const& aPoint, bool fPar = false) +size_t CreateTreePoint(depth_t depth, std::span const> const& aPoint, bool fPar = false) { using TreePoint = TreePointND; auto box = BoundingBoxND{}; @@ -57,3 +57,77 @@ static size_t CreateTreePoint(depth_t depth, std::span con return nt.GetNodes().size(); } + + +template +constexpr PointND CreateBoxMax(PointND const& pt, double size) +{ + auto ptMax = pt; + for (size_t iDim = 0; iDim < DIMENSION_NO; ++iDim) + ptMax[iDim] = pt[iDim] + size; + + return ptMax; +} + + +template +BoundingBoxND CreateSearcBox(double rBegin, double rSize) +{ + auto box = BoundingBoxND{}; + for (dim_t iDim = 0; iDim < DIMENSION_NO; ++iDim) + box.Min[iDim] = rBegin; + + box.Max = CreateBoxMax(box.Min, rSize); + return box; +} + + +template +constexpr std::vector> GenerateBoxesRandom(size_t nNumber, int seed = 0) +{ + if (nNumber == 0) + return {}; + + auto constexpr rMax = 8.0; + auto constexpr rUnit = 1.0; + auto aBox = std::vector>(nNumber); + aBox[0].Max = CreateBoxMax(PointND(), rMax); + if (nNumber == 1) + return aBox; + + size_t iNumber = 1; + + // Corner points + { + for (dim_t iDim = 0; iDim < DIMENSION_NO && iNumber < nNumber; ++iDim, ++iNumber) + { + aBox[iNumber].Min[iDim] = rMax - rUnit; + aBox[iNumber].Max = CreateBoxMax(aBox[iNumber].Min, rUnit); + } + if (iNumber == nNumber) + return aBox; + + + for (dim_t iDim = 0; iDim < DIMENSION_NO; ++iDim) + aBox[iNumber].Min[iDim] = rMax - rUnit; + + aBox[iNumber].Max = CreateBoxMax(aBox[iNumber].Min, rUnit); + + ++iNumber; + } + + srand(seed); + + { + for (size_t iRemain = 1; iNumber < nNumber; ++iNumber, ++iRemain) + { + auto const iNumberBox = nNumber - iNumber - 1; + for (dim_t iDim = 0; iDim < DIMENSION_NO && iNumber < nNumber; ++iDim) + aBox[iNumberBox].Min[iDim] = double(rand() % 100) * ((rMax - 1.0) / 100.0); + + aBox[iNumberBox].Max = CreateBoxMax(aBox[iNumberBox].Min, double(rand() % 100) * (1.0 * rUnit / 100.0)); + } + } + + return aBox; +} \ No newline at end of file