forked from fwyzard/soa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_v6_cppunit.cc
144 lines (119 loc) · 4.73 KB
/
test_v6_cppunit.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#include <stdexcept>
#include "cppunit/extensions/HelperMacros.h"
/*
* Unit tests skeleton based on DataFormats/Common/test/ (testDataFormatsCommon)
*/
#include "soa_v6.h"
class testSoA: public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(testSoA);
CPPUNIT_TEST(initialTest);
CPPUNIT_TEST(checkAlignment);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {}
void tearDown() {}
void initialTest();
void checkAlignment();
};
CPPUNIT_TEST_SUITE_REGISTRATION(testSoA);
#define check(X) \
do { std::cout << #X " is " << (X) << std::endl; } while(false)
// declare a statically-sized SoA, templated on the column size and (optional) alignment
declare_SoA_template(SoA,
// predefined static scalars
// size_t size;
// size_t alignment;
// columns: one value per element
SoA_column(double, x),
SoA_column(double, y),
SoA_column(double, z),
SoA_column(uint16_t, colour),
SoA_column(int32_t, value),
SoA_column(const char *, name),
// scalars: one value for the whole structure
SoA_scalar(const char *, description)
);
void testSoA::initialTest() {
std::cout << std::boolalpha;
SoA::dump(10, 8);
// CPPUNIT_ASSERT_EQUAL_MESSAGE("Size of SoA<1>",
// 3 * sizeof(double)
// + (sizeof(uint16_t) / sizeof(int32_t) + 1) * sizeof(int32_t) // Take into account the padding to align the next element
// + sizeof(int32_t)
// + 2 * sizeof(const char *),
// sizeof(SoA<1>));
//check(sizeof(SoA<1>));
std::cout << std::endl;
SoA::dump(10);
SoA::dump(31);
SoA::dump(32);
std::cout << std::endl;
SoA::dump(1, 64);
SoA::dump(10, 64);
SoA::dump(31, 64);
SoA::dump(32, 64);
std::cout << std::endl;
SoA soa(new std::byte[SoA::computeDataSize(10,32)], 10, 32);
check(& soa.z()[7] == & (soa[7].z));
soa[7].x = 0.;
soa[7].y = 3.1416;
soa[7].z = -1.;
soa[7].colour = 42;
soa[7].value = 9999;
soa[7].name = "element";
soa[9] = soa[7];
CPPUNIT_ASSERT(& soa.z()[7] == & (soa[7].z));
}
template <typename T>
void checkValuesAlignment(SoA &soa, T SoA::element::*member, const std::string & memberName, uint32_t bitAlignment) {
if (bitAlignment % 8) CPPUNIT_FAIL("bitAlignment not byte aligned.");
size_t byteAlignment = bitAlignment / 8;
for (size_t i=0; i<soa.nElements(); i++) {
// Check that each value is aligned
if (reinterpret_cast<std::uintptr_t>(&(soa[i].*member)) % byteAlignment
!= (i * T::valueSize) %byteAlignment ) {
std::stringstream err;
err << "Misaligned value: " << memberName << " at index=" << i
<< " address=" << &(soa[i].*member) << " byteAlignment=" << byteAlignment
<< " address lower part: " << reinterpret_cast<std::uintptr_t>(&(soa[i].*member)) % byteAlignment
<< " expected address lower part: " << ((i * T::valueSize) % byteAlignment)
<< " size=" << soa.nElements() << " align=" << soa.byteAlignment();
CPPUNIT_FAIL(err.str());
}
// Check that all values except the first-in rows (address 0 modulo alignment)
// are contiguous to their predecessors in memory (this will detect cutting
// memory/cache/etc... lines in unexpected places (for blocked SoA like AoSoA)
if ((reinterpret_cast<std::uintptr_t>(&(soa[i].*member)) % byteAlignment)
&& (reinterpret_cast<std::uintptr_t>(&(soa[i - 1].*member)) + T::valueSize
!= reinterpret_cast<std::uintptr_t>(&(soa[i].*member)))) {
std::stringstream err;
err << "Unexpected non-contiguity: " << memberName << " at index=" << i
<< " address=" << &(soa[i].*member) << " is not contiguous to "
<< memberName << " at index=" << i - 1 << "address=" << &(soa[i - 1].*member)
<< " size=" << soa.nElements() << " align=" << soa.byteAlignment() << " valueSize=" << T::valueSize;
CPPUNIT_FAIL(err.str());
}
}
}
void checkSoAAlignment(size_t nElements, size_t byteAlignment, uint32_t bitAlignment) {
SoA soa(new std::byte[SoA::computeDataSize(nElements,byteAlignment)], nElements, byteAlignment);
checkValuesAlignment(soa, &SoA::element::x, "x", bitAlignment);
checkValuesAlignment(soa, &SoA::element::y, "y", bitAlignment);
checkValuesAlignment(soa, &SoA::element::z, "z", bitAlignment);
checkValuesAlignment(soa, &SoA::element::colour, "colour", bitAlignment);
checkValuesAlignment(soa, &SoA::element::value, "value", bitAlignment);
checkValuesAlignment(soa, &SoA::element::name, "name", bitAlignment);
}
void testSoA::checkAlignment() {
checkSoAAlignment(1, 1, 8);
checkSoAAlignment(10, 1, 8);
checkSoAAlignment(31, 1, 8);
checkSoAAlignment(32, 1, 8);
checkSoAAlignment(1,64, 8*64);
checkSoAAlignment(10,64, 8*64);
checkSoAAlignment(31,64, 8*64);
checkSoAAlignment(32,64, 8*64);
}