BulkAllocator_test.cc
Go to the documentation of this file.
1 /**
2  * @file BulkAllocator_test.cc
3  * @brief Tests the bulk allocator
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date 20140817
6  * @version 1.0
7  *
8  * See http://www.boost.org/libs/test for the Boost test library home page.
9  *
10  * Timing:
11  * version 1.0 takes less than 3" on a 3 GHz machine FIXME
12  */
13 
14 // C/C++ standard libraries
15 #include <map>
16 #include <random>
17 
18 // Boost libraries
19 /*
20  * Boost Magic: define the name of the module;
21  * and do that before the inclusion of Boost unit test headers
22  * because it will change what they provide.
23  * Among the those, there is a main() function and some wrapping catching
24  * unhandled exceptions and considering them test failures, and probably more.
25  * This also makes fairly complicate to receive parameters from the command line
26  * (for example, a random seed).
27  */
28 #define BOOST_TEST_MODULE ( BulkAllocator_test )
29 #include "boost/test/unit_test.hpp"
30 
31 // LArSoft libraries
33 
34 
35 /// The seed for the default random engine
36 constexpr unsigned int RandomSeed = 12345;
37 
38 
39 //------------------------------------------------------------------------------
40 //--- Test code
41 //
42 
43 /**
44  * @brief Tests bulk allocator with a vector of maps (Hough transfort use case)
45  *
46  * The test consists in filling a lot of points into a 2D sparse "image" (or
47  * histogram).
48  * Two structures are maintained, one with the standard STL allocator, another
49  * with the BulkAllocator.
50  * The test fails if the two images do not match.
51  */
53 
54  // the structure we are testing is a 2D "image" of integers;
55  // image is mostly empty (zero), but each abscissa has roughly the same
56  // number of non-empty pixels (NPoints), and at least one of them.
57 
58  constexpr unsigned int NPoints = 1000;
59  constexpr unsigned int NAngles = 10800;
60  constexpr unsigned int NDist = 2500; // half distance
61 
62  typedef std::map<int, int> BaseMap_t;
63 
64  // STL allocator
65  std::vector<std::map<
66  int, int, BaseMap_t::key_compare,
67  std::allocator<BaseMap_t::value_type>
68  >> stl_image(NAngles);
69 
70  // BulkAllocator
71  // Normally, I would declare an allocator like
72  // lar::BulkAllocator<BaseMap_t::value_type> MyAllocator(500000);
73  // and use it to initialize the STL container; then the STL would use the same
74  // allocator or a copy of it or a default-constructed version of the same
75  // allocator class, and that does not matter because all of them refer
76  // internally to the same base allocator for BaseMap_t::value_type.
77  // But map rebinds the allocator to one based not on BaseMap_t::value_type,
78  // but on the tree node used in the map implementation; that allocator is
79  // of a different type, and does not refer to
80  // lar::BulkAllocator<BaseMap_t::value_type> any more.
81  // Therefore I let map do its tricks...
82  std::vector<std::map<
83  int, int, BaseMap_t::key_compare,
85  >> bulk_image(NAngles);
86  // ... and then I change the underlying allocator directly;
87  // Unfortunately this trick is implementation-dependent, in that there is no
88  // requirement for map to expose the allocator it really uses.
89  // Here the non-standard part is the name of the node type, std::_Rb_tree_node
91  ::SetChunkSize(500000);
92 
93  static std::default_random_engine random_engine(RandomSeed);
94  std::uniform_real_distribution<float> uniform(-1., 1.);
95 
96  for (unsigned int iPoint = 0; iPoint != NPoints; ++iPoint) {
97  // we add here some simple image, not to strain the test;
98  // this is a straight line
99  const float offset = uniform(random_engine) * NDist;
100  const float slope = uniform(random_engine);
101  float d = offset;
102  for (size_t iAngle = 0; iAngle < NAngles; ++iAngle) {
103  // add one entry on the (angle ; distance) plane
104  ++(stl_image[iAngle][int(d)]);
105  ++(bulk_image[iAngle][int(d)]);
106  // prepare for the next point; wrap in the [-NDist, NDist[ range
107  d += slope;
108  while (d >= (float) NDist) d -= 2*NDist;
109  while (d < 0) d += 2*NDist;
110  } // for iAngle
111  } // for iPoint
112 
113  // we have to provide a comparison between two "different" structures
114  // (having different allocators is enough to make them unrelated)
115  bool bSame = true;
116  auto stl_begin = stl_image.cbegin();
117  for (const auto& bulk_map: bulk_image) {
118  // the std::equal() call compares pairs (int, int) of each map
119  if (std::equal(bulk_map.begin(), bulk_map.end(), (stl_begin++)->begin()))
120  continue;
121  bSame = false;
122  break;
123  } // for
124 
125  BOOST_TEST(bSame);
126 
127 } // RunHoughTransformTreeTest()
128 
129 
130 //------------------------------------------------------------------------------
131 //--- registration of tests
132 //
133 // Boost needs now to know which tests we want to run.
134 // Tests are "automatically" registered, hence the BOOST_AUTO_TEST_CASE()
135 // macro name. The argument is a name for the test; each test will have a
136 // number of checks and it will fail if any of them does.
137 //
138 
139 BOOST_AUTO_TEST_CASE(RunHoughTransformTree) {
141  std::cout << "Done." << std::endl;
142 }
constexpr unsigned int RandomSeed
The seed for the default random engine.
struct vector vector
void RunHoughTransformTreeTest()
Tests bulk allocator with a vector of maps (Hough transfort use case)
BOOST_AUTO_TEST_CASE(RunHoughTransformTree)
Aggressive allocator reserving a lot of memory in advance.
Definition: BulkAllocator.h:92
Memory allocator for large amount of (small) objects.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
QTextStream & endl(QTextStream &s)