Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-06 22:42:48

0001 #include <Eigen/Core>
0002 #include <Eigen/Dense>
0003 
0004 #define CATCH_CONFIG_MAIN
0005 #include <catch.hpp>
0006 
0007 #include "DataFormats/SoATemplate/interface/SoALayout.h"
0008 
0009 GENERATE_SOA_LAYOUT(SoAPositionTemplate,
0010                     SOA_COLUMN(float, x),
0011                     SOA_COLUMN(float, y),
0012                     SOA_COLUMN(float, z),
0013                     SOA_SCALAR(int, detectorType))
0014 
0015 using SoAPosition = SoAPositionTemplate<>;
0016 using SoAPositionView = SoAPosition::View;
0017 using SoAPositionConstView = SoAPosition::ConstView;
0018 
0019 GENERATE_SOA_LAYOUT(SoAPCATemplate,
0020                     SOA_COLUMN(float, eigenvalues),
0021                     SOA_COLUMN(float, eigenvector_1),
0022                     SOA_COLUMN(float, eigenvector_2),
0023                     SOA_COLUMN(float, eigenvector_3),
0024                     SOA_EIGEN_COLUMN(Eigen::Vector3d, candidateDirection))
0025 
0026 using SoAPCA = SoAPCATemplate<>;
0027 using SoAPCAView = SoAPCA::View;
0028 using SoAPCAConstView = SoAPCA::ConstView;
0029 
0030 GENERATE_SOA_LAYOUT(GenericSoATemplate,
0031                     SOA_COLUMN(float, xPos),
0032                     SOA_COLUMN(float, yPos),
0033                     SOA_COLUMN(float, zPos),
0034                     SOA_EIGEN_COLUMN(Eigen::Vector3d, candidateDirection))
0035 
0036 using GenericSoA = GenericSoATemplate<cms::soa::CacheLineSize::IntelCPU>;
0037 using GenericSoAView = GenericSoA::View;
0038 using GenericSoAConstView = GenericSoA::ConstView;
0039 
0040 TEST_CASE("SoAGenericView") {
0041   // common number of elements for the SoAs
0042   const std::size_t elems = 17;
0043 
0044   // buffer sizes
0045   const std::size_t positionBufferSize = SoAPosition::computeDataSize(elems);
0046   const std::size_t pcaBufferSize = SoAPCA::computeDataSize(elems);
0047 
0048   // memory buffer for the SoA of positions
0049   std::unique_ptr<std::byte, decltype(std::free) *> bufferPos{
0050       reinterpret_cast<std::byte *>(aligned_alloc(SoAPosition::alignment, positionBufferSize)), std::free};
0051   // memory buffer for the SoA of the PCA
0052   std::unique_ptr<std::byte, decltype(std::free) *> bufferPCA{
0053       reinterpret_cast<std::byte *>(aligned_alloc(SoAPCA::alignment, pcaBufferSize)), std::free};
0054 
0055   // SoA Layouts
0056   SoAPosition position{bufferPos.get(), elems};
0057   SoAPCA pca{bufferPCA.get(), elems};
0058 
0059   // SoA Views
0060   SoAPositionView positionView{position};
0061   SoAPositionConstView positionConstView{position};
0062   SoAPCAView pcaView{pca};
0063   SoAPCAConstView pcaConstView{pca};
0064 
0065   // fill up
0066   for (size_t i = 0; i < elems; i++) {
0067     positionView[i] = {i * 1.0f, i * 2.0f, i * 3.0f};
0068   }
0069   positionView.detectorType() = 1;
0070 
0071   float time = 0.01;
0072   for (size_t i = 0; i < elems; i++) {
0073     pcaView[i].eigenvector_1() = positionView[i].x() / time;
0074     pcaView[i].eigenvector_2() = positionView[i].y() / time;
0075     pcaView[i].eigenvector_3() = positionView[i].z() / time;
0076     pcaView[i].candidateDirection()(0) = positionView[i].x() / time;
0077     pcaView[i].candidateDirection()(1) = positionView[i].y() / time;
0078     pcaView[i].candidateDirection()(2) = positionView[i].z() / time;
0079   }
0080 
0081   SECTION("Generic View") {
0082     // addresses and size of the SoA columns
0083     const auto posRecs = positionView.records();
0084     const auto pcaRecs = pcaView.records();
0085 
0086     // building the View with runtime check for the size
0087     GenericSoAView genericView(posRecs.x(), posRecs.y(), posRecs.z(), pcaRecs.candidateDirection());
0088 
0089     // Check for equality of memory addresses
0090     REQUIRE(genericView.metadata().addressOf_xPos() == positionView.metadata().addressOf_x());
0091     REQUIRE(genericView.metadata().addressOf_yPos() == positionView.metadata().addressOf_y());
0092     REQUIRE(genericView.metadata().addressOf_zPos() == positionView.metadata().addressOf_z());
0093     REQUIRE(genericView.metadata().addressOf_candidateDirection() == pcaView.metadata().addressOf_candidateDirection());
0094 
0095     // Check for reference to original SoA
0096     genericView[3].xPos() = 0.;
0097     REQUIRE(genericView[3].xPos() == positionConstView[3].x());
0098   }
0099 
0100   SECTION("Generic ConstView") {
0101     // addresses and size of the SoA columns
0102     const auto posRecs = positionConstView.records();
0103     const auto pcaRecs = pcaConstView.records();
0104 
0105     // building the ConstView with runtime check for the size
0106     GenericSoAConstView genericConstView(posRecs.x(), posRecs.y(), posRecs.z(), pcaRecs.candidateDirection());
0107 
0108     // Check for equality of memory addresses
0109     REQUIRE(genericConstView.metadata().addressOf_xPos() == positionConstView.metadata().addressOf_x());
0110     REQUIRE(genericConstView.metadata().addressOf_yPos() == positionConstView.metadata().addressOf_y());
0111     REQUIRE(genericConstView.metadata().addressOf_zPos() == positionConstView.metadata().addressOf_z());
0112     REQUIRE(genericConstView.metadata().addressOf_candidateDirection() ==
0113             pcaConstView.metadata().addressOf_candidateDirection());
0114   }
0115 
0116   SECTION("Generic ConstView from Views") {
0117     // addresses and size of the SoA columns
0118     const auto posRecs = positionView.records();
0119     const auto pcaRecs = pcaView.records();
0120 
0121     // building the ConstView with runtime check for the size
0122     GenericSoAConstView genericConstView(posRecs.x(), posRecs.y(), posRecs.z(), pcaRecs.candidateDirection());
0123 
0124     // Check for reference to the Generic SoA - it is possible to modify the ConstView by reference modifying the Views
0125     positionView[3].x() = 0.;
0126     REQUIRE(genericConstView[3].xPos() == positionView[3].x());
0127   }
0128 
0129   SECTION("Deep copy the Generic View") {
0130     // building the Layout
0131     const std::size_t genericBufferSize = GenericSoA::computeDataSize(elems);
0132     std::unique_ptr<std::byte, decltype(std::free) *> bufferGeneric{
0133         reinterpret_cast<std::byte *>(aligned_alloc(GenericSoA::alignment, genericBufferSize)), std::free};
0134     GenericSoA genericSoA(bufferGeneric.get(), elems);
0135 
0136     // building the Generic View
0137     const auto posRecs = positionView.records();
0138     const auto pcaRecs = pcaView.records();
0139     GenericSoAView genericView(posRecs.x(), posRecs.y(), posRecs.z(), pcaRecs.candidateDirection());
0140 
0141     // aggregate the columns from the view with runtime check for the size
0142     genericSoA.deepCopy(genericView);
0143 
0144     // building the View of the new SoA
0145     GenericSoAView genericSoAView{genericSoA};
0146 
0147     // Check for inequality of memory addresses
0148     REQUIRE(genericSoAView.metadata().addressOf_xPos() != positionConstView.metadata().addressOf_x());
0149     REQUIRE(genericSoAView.metadata().addressOf_yPos() != positionConstView.metadata().addressOf_y());
0150     REQUIRE(genericSoAView.metadata().addressOf_zPos() != positionConstView.metadata().addressOf_z());
0151     REQUIRE(genericSoAView.metadata().addressOf_candidateDirection() !=
0152             pcaConstView.metadata().addressOf_candidateDirection());
0153 
0154     // Check for column alignments
0155     REQUIRE(0 ==
0156             reinterpret_cast<uintptr_t>(genericSoAView.metadata().addressOf_xPos()) % decltype(genericSoA)::alignment);
0157     REQUIRE(0 ==
0158             reinterpret_cast<uintptr_t>(genericSoAView.metadata().addressOf_yPos()) % decltype(genericSoA)::alignment);
0159     REQUIRE(0 ==
0160             reinterpret_cast<uintptr_t>(genericSoAView.metadata().addressOf_zPos()) % decltype(genericSoA)::alignment);
0161     REQUIRE(0 == reinterpret_cast<uintptr_t>(genericSoAView.metadata().addressOf_candidateDirection()) %
0162                      decltype(genericSoA)::alignment);
0163 
0164     // Check for contiguity of columns
0165     REQUIRE(reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_xPos()) +
0166                 cms::soa::alignSize(elems * sizeof(float), GenericSoA::alignment) ==
0167             reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_yPos()));
0168     REQUIRE(reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_yPos()) +
0169                 cms::soa::alignSize(elems * sizeof(float), GenericSoA::alignment) ==
0170             reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_zPos()));
0171     REQUIRE(reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_zPos()) +
0172                 cms::soa::alignSize(elems * sizeof(float), GenericSoA::alignment) ==
0173             reinterpret_cast<std::byte *>(genericSoAView.metadata().addressOf_candidateDirection()));
0174 
0175     // Ckeck the correctness of the copy
0176     for (size_t i = 0; i < elems; i++) {
0177       REQUIRE(genericSoAView[i].xPos() == positionConstView[i].x());
0178       REQUIRE(genericSoAView[i].yPos() == positionConstView[i].y());
0179       REQUIRE(genericSoAView[i].zPos() == positionConstView[i].z());
0180       REQUIRE(genericSoAView[i].candidateDirection()(0) == pcaConstView[i].candidateDirection()(0));
0181       REQUIRE(genericSoAView[i].candidateDirection()(1) == pcaConstView[i].candidateDirection()(1));
0182       REQUIRE(genericSoAView[i].candidateDirection()(2) == pcaConstView[i].candidateDirection()(2));
0183     }
0184 
0185     // Check for the independency of the aggregated SoA
0186     genericSoAView[3].xPos() = 0.;
0187     REQUIRE(genericSoAView[3].xPos() != positionView[3].x());
0188   }
0189 }