ATLAS Offline Software
Loading...
Searching...
No Matches
columnar::TestUtils Namespace Reference

Classes

class  Benchmark
 this is a simple benchmarking helper class wrapping timers from std::chrono More...
struct  BranchPerfData
 the performance data for reading a single branch/column More...
class  BranchReader
class  BranchReaderArray
class  ColumnarTestToolHandle
 a handle to a columnar tool for running tests More...
struct  ColumnDataEventCount
struct  ColumnDataMetNames
struct  ColumnDataOutputMet
struct  ColumnDataOutVector
struct  ColumnDataSamplingPattern
struct  ColumnDataScalar
struct  ColumnDataVector
struct  ColumnDataVectorVector
struct  ColumnDataVectorVectorVector
struct  ColumnMapType
class  IColumnData
class  IXAODToolCaller
 a wrapper around a CP tool in xAOD mdoe to call it in the PHYSLITE test More...
class  ManualColumnData
 a class that holds manually specified column data More...
struct  TestDefinition
 the general configuration for a single test More...
struct  ToolPerfData
 the performance data for running a single tool More...
class  ToolWrapperData
 a class that holds a reference to a ToolColumnVectorMap and a ColumnVectorData More...
struct  UserConfiguration
 a struct holding user configuration for the PHYSLITE tests More...

Functions

void checkExpectation (const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData, const std::type_info &expectationType, std::size_t expectationSize, const void *expectationData)
void printExpectedOutput (const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData)
void runXaodArrayTest (const UserConfiguration &userConfiguration, const TestDefinition &testDefinition)

Variables

static const std::unordered_map< std::string, SG::sgkey_tknownKeys

Function Documentation

◆ checkExpectation()

void columnar::TestUtils::checkExpectation ( const std::string & columnName,
const std::type_info & outputType,
std::size_t outputSize,
const void * outputData,
const std::type_info & expectationType,
std::size_t expectationSize,
const void * expectationData )

Definition at line 46 of file ExpectationCompare.cxx.

47 {
48 SCOPED_TRACE (columnName);
49 ASSERT_EQ (outputType, expectationType);
50 if (outputType == typeid(float))
51 checkExpectationTyped (columnName, std::span<const float> (static_cast<const float*> (outputData), outputSize), std::span<const float> (static_cast<const float*> (expectationData), expectationSize));
52 else if (outputType == typeid(char))
53 checkExpectationTyped (columnName, std::span<const char> (static_cast<const char*> (outputData), outputSize), std::span<const char> (static_cast<const char*> (expectationData), expectationSize));
54 else if (outputType == typeid(int))
55 checkExpectationTyped (columnName, std::span<const int> (static_cast<const int*> (outputData), outputSize), std::span<const int> (static_cast<const int*> (expectationData), expectationSize));
56 else if (outputType == typeid(std::uint8_t))
57 checkExpectationTyped (columnName, std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (outputData), outputSize), std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (expectationData), expectationSize));
58 else if (outputType == typeid(std::uint16_t))
59 checkExpectationTyped (columnName, std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (outputData), outputSize), std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (expectationData), expectationSize));
60 else if (outputType == typeid(std::uint32_t))
61 checkExpectationTyped (columnName, std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (outputData), outputSize), std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (expectationData), expectationSize));
62 else if (outputType == typeid(std::uint64_t))
63 checkExpectationTyped (columnName, std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (outputData), outputSize), std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (expectationData), expectationSize));
64 else if (outputType == typeid(std::size_t))
65 checkExpectationTyped (columnName, std::span<const std::size_t> (static_cast<const std::size_t*> (outputData), outputSize), std::span<const std::size_t> (static_cast<const std::size_t*> (expectationData), expectationSize));
66 else
67 throw std::logic_error ("received unsupported type " + boost::core::demangle(outputType.name()) + " for column compare, cast value or extend test handler to support it");
68 }

◆ printExpectedOutput()

void columnar::TestUtils::printExpectedOutput ( const std::string & columnName,
const std::type_info & outputType,
std::size_t outputSize,
const void * outputData )

Definition at line 93 of file ExpectationCompare.cxx.

94 {
95 if (outputType == typeid(float))
96 printExpectedOutputTyped (columnName, std::span<const float> (static_cast<const float*> (outputData), outputSize));
97 else if (outputType == typeid(char))
98 printExpectedOutputTyped (columnName, std::span<const char> (static_cast<const char*> (outputData), outputSize));
99 else if (outputType == typeid(int))
100 printExpectedOutputTyped (columnName, std::span<const int> (static_cast<const int*> (outputData), outputSize));
101 else if (outputType == typeid(std::uint8_t))
102 printExpectedOutputTyped (columnName, std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (outputData), outputSize));
103 else if (outputType == typeid(std::uint16_t))
104 printExpectedOutputTyped (columnName, std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (outputData), outputSize));
105 else if (outputType == typeid(std::uint32_t))
106 printExpectedOutputTyped (columnName, std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (outputData), outputSize));
107 else if (outputType == typeid(std::uint64_t))
108 printExpectedOutputTyped (columnName, std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (outputData), outputSize));
109 else if (outputType == typeid(std::size_t))
110 printExpectedOutputTyped (columnName, std::span<const std::size_t> (static_cast<const std::size_t*> (outputData), outputSize));
111 else
112 throw std::logic_error ("received unsupported type " + boost::core::demangle(outputType.name()) + " for column printout, cast value or extend test handler to support it");
113 }

◆ runXaodArrayTest()

void columnar::TestUtils::runXaodArrayTest ( const UserConfiguration & userConfiguration,
const TestDefinition & testDefinition )

Definition at line 316 of file PhysliteTestXaodArray.cxx.

317 {
318 using namespace asg::msgUserCode;
319
320 xAOD::TEvent event;
321 xAOD::TStore store;
322 ANA_CHECK_THROW (event.readFrom (testDefinition.file));
323
324 auto *myTool = dynamic_cast<ColumnarTool<ColumnarModeXAODArray>*>(testDefinition.tool);
325 if (!myTool)
326 throw std::runtime_error ("tool is not a ColumnarTool<ColumnarModeXAODArray>");
327 if (!testDefinition.containerRenames.empty())
328 renameContainers (*myTool, testDefinition.containerRenames);
329 ColumnVectorHeader columnHeader;
330 ToolColumnVectorMap toolWrapper (columnHeader, *myTool);
331
332 std::unordered_map<std::string,TestUtils::ColumnDataXA> requestedColumns;
333 for (auto& column : myTool->getColumnInfo())
334 requestedColumns[column.name].info = std::move (column);
335 for (auto& [name, data] : requestedColumns)
336 {
337 if (data.info.isOffset)
338 {
339 if (*data.info.type != typeid(ColumnarOffsetType))
340 throw std::runtime_error ("unexpected type for offset column: " + name + " " + data.info.type->name());
341 if (name == numberOfEventsName)
342 {
343 data.reader = std::make_shared<TestUtils::ColumnDataXAEventInfo> (data.info);
344 } else if (data.info.offsetName == numberOfEventsName)
345 {
346 if (name == "AnalysisMuons")
347 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::MuonContainer>> (data.info, userConfiguration);
348 else if (name == "AnalysisElectrons")
349 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::ElectronContainer>> (data.info, userConfiguration);
350 else if (name == "AnalysisPhotons")
351 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::PhotonContainer>> (data.info, userConfiguration);
352 else if (name == "egammaClusters")
353 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::CaloClusterContainer>> (data.info, userConfiguration);
354 else if (name == "GSFTrackParticles")
355 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::TrackParticleContainer>> (data.info, userConfiguration);
356 else if (name == "GSFConversionVertices")
357 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::VertexContainer>> (data.info, userConfiguration);
358 }
359 } else
360 {
361 if (*data.info.type == typeid(float))
362 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<float>> (data.info, userConfiguration);
363 else if (*data.info.type == typeid(double))
364 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<double>> (data.info, userConfiguration);
365 else if (*data.info.type == typeid(char))
366 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<char>> (data.info, userConfiguration);
367 else if (*data.info.type == typeid(std::uint8_t))
368 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint8_t>> (data.info, userConfiguration);
369 else if (*data.info.type == typeid(std::uint16_t))
370 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint16_t>> (data.info, userConfiguration);
371 else if (*data.info.type == typeid(std::uint32_t))
372 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint32_t>> (data.info, userConfiguration);
373 else if (*data.info.type == typeid(std::uint64_t))
374 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint64_t>> (data.info, userConfiguration);
375 else if (*data.info.type == typeid(std::vector<float>))
376 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<float>>> (data.info, userConfiguration);
377 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::CaloClusterContainer>>))
378 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::CaloClusterContainer>>>> (data.info, userConfiguration);
379 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::TrackParticleContainer>>))
380 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::TrackParticleContainer>>>> (data.info, userConfiguration);
381 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::VertexContainer>>))
382 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::VertexContainer>>>> (data.info, userConfiguration);
383 }
384 }
385
386 bool allColumnsHandled = true;
387 for (auto& [name, data] : requestedColumns)
388 {
389 if (!data.reader)
390 {
391 allColumnsHandled = false;
392 std::cout << "WARNING: no handling for requested column: name=" << name << " offset=" << data.info.offsetName << " type=" << boost::core::demangle(data.info.type->name()) << std::endl;
393 }
394 }
395 if (!allColumnsHandled)
396 {
397 ADD_FAILURE() << "not all requested columns could be handled";
398 return;
399 }
400
401 for (auto& [name, data]: requestedColumns)
402 {
403 data.reader->connect (data, requestedColumns);
404 }
405
406 Benchmark benchmarkEmptyClear (testDefinition.name + " empty clear");
407 Benchmark benchmarkCallClear (testDefinition.name + " call clear");
408 Benchmark benchmarkGetEntry (testDefinition.name + " getEntry");
409 Benchmark benchmarkCheck (testDefinition.name + " check");
410 Benchmark benchmarkCall2 (testDefinition.name + " call2");
411 Benchmark benchmarkCall (testDefinition.name + " call");
412 Benchmark benchmarkEmpty ("empty");
413
414 const auto numberOfEvents = event.getEntries();
415 if (numberOfEvents == 0){
416 throw std::runtime_error ("ColumnarPhysLiteTest: numberOfEvents == 0");
417 }
418 Long64_t entry = 0;
419
420 // Instead of running for a fixed number of events, we run for a
421 // fixed amount of time. That is because individual tools can
422 // vary wildly in how long they take to run, and we mostly want to
423 // make sure that we ran the tool enough to get a precise
424 // performance estimate.
425 const auto startTime = std::chrono::high_resolution_clock::now();
426 for (; (std::chrono::high_resolution_clock::now() - startTime) < userConfiguration.targetTime; ++entry)
427 {
428 benchmarkEmpty.startTimer ();
429 benchmarkEmpty.stopTimer ();
430
431 benchmarkGetEntry.startTimer ();
432 event.getEntry (entry % numberOfEvents);
433 benchmarkGetEntry.stopTimer ();
434
435 ColumnVectorData columnData (&columnHeader);
436 for (auto& [name, data] : requestedColumns)
437 ASSERT_SUCCESS (data.reader->retrieveContainer (event, store, columnData));
438 for (auto& [name, data] : requestedColumns)
439 data.reader->retrieveAuxData (columnData);
440
441 benchmarkCheck.startTimer ();
442 columnData.checkData ();
443 benchmarkCheck.stopTimer ();
444 benchmarkCall.startTimer ();
445 columnData.callNoCheck (*myTool);
446 benchmarkCall.stopTimer ();
447 if (userConfiguration.runToolTwice)
448 {
449 benchmarkCall2.startTimer ();
450 columnData.callNoCheck (*myTool);
451 benchmarkCall2.stopTimer ();
452 }
453
454 benchmarkCallClear.startTimer ();
455 store.clear ();
456 benchmarkCallClear.stopTimer ();
457 benchmarkEmptyClear.startTimer ();
458 store.clear ();
459 benchmarkEmptyClear.stopTimer ();
460 }
461 std::cout << "Total entries read: " << entry << std::endl;
462 const float emptyTime = benchmarkEmpty.getEntryTime(0).value();
463 std::cout << "Empty benchmark time: " << emptyTime << "ns" << std::endl;
464 benchmarkEmpty.setSilence();
465 std::cout << "Average getEntry time: " << benchmarkGetEntry.getEntryTime(emptyTime).value() << "ns" << std::endl;
466 benchmarkGetEntry.setSilence();
467 std::cout << "Average clear time: " << benchmarkCallClear.getEntryTime(emptyTime).value() << "ns" << " (empty=" << benchmarkEmptyClear.getEntryTime(emptyTime).value() << "ns)" << std::endl;
468 benchmarkCallClear.setSilence();
469 benchmarkEmptyClear.setSilence();
470
471 // Column performance table
472 {
473 std::vector<BranchPerfData> columnPerfData;
475 summary.name = "total";
476 summary.timeRead = 0;
477 summary.timeReadAgain = 0;
478 summary.timeShallowCopy = 0;
479 summary.timeShallowRegister = 0;
480 for (auto& [name, data] : requestedColumns)
481 {
482 auto perfData = data.reader->getPerfData(emptyTime);
483 if (perfData.timeRead.has_value() || perfData.timeReadAgain.has_value())
484 {
485 columnPerfData.push_back(perfData);
486 summary.timeRead.value() += perfData.timeRead.value_or(0);
487 summary.timeReadAgain.value() += perfData.timeReadAgain.value_or(0);
488 summary.timeShallowCopy.value() += perfData.timeShallowCopy.value_or(0);
489 summary.timeShallowRegister.value() += perfData.timeShallowRegister.value_or(0);
490 }
491 }
492 std::sort(columnPerfData.begin(), columnPerfData.end(), [](const auto& a, const auto& b) { return a.name < b.name; });
493 columnPerfData.push_back(summary);
494
495 const std::size_t nameWidth = std::max_element(columnPerfData.begin(), columnPerfData.end(), [](const auto& a, const auto& b) { return a.name.size() < b.name.size(); })->name.size();
496 std::string header = std::format("{:{}} | 1st(ns) | 2nd(ns) | shallow copy(ns)", "column name", nameWidth);
497 std::cout << "\n" << header << std::endl;
498 std::cout << std::string(header.size(), '-') << std::endl;
499 for (auto& data : columnPerfData)
500 {
501 if (data.name == "total")
502 std::cout << std::string(header.size(), '-') << std::endl;
503 std::cout << std::format("{:{}} |", data.name, nameWidth);
504 if (data.timeRead)
505 std::cout << std::format("{:>8.0f} |", data.timeRead.value());
506 else
507 std::cout << " |";
508 if (data.timeReadAgain)
509 std::cout << std::format("{:>8.1f} |", data.timeReadAgain.value());
510 else
511 std::cout << " |";
512 if (data.timeShallowCopy || data.timeShallowRegister)
513 std::cout << std::format("{:>10.0f} +{:>5.0f}", data.timeShallowCopy.value_or(-1), data.timeShallowRegister .value_or(-1));
514 std::cout << std::endl;
515 }
516 }
517
518 // Tool performance table
519 {
520 std::vector<ToolPerfData> toolPerfData;
521 toolPerfData.emplace_back();
522 toolPerfData.back().name = testDefinition.name;
523 toolPerfData.back().timeCall = benchmarkCall.getEntryTime(emptyTime);
524 if (userConfiguration.runToolTwice)
525 toolPerfData.back().timeCall2 = benchmarkCall2.getEntryTime(emptyTime);
526 toolPerfData.back().timeCheck = benchmarkCheck.getEntryTime(emptyTime);
527 benchmarkCall.setSilence();
528 benchmarkCall2.setSilence();
529 benchmarkCheck.setSilence();
530
531 const std::size_t nameWidth = std::max_element(toolPerfData.begin(), toolPerfData.end(), [](const auto& a, const auto& b) { return a.name.size() < b.name.size(); })->name.size();
532 std::string header = std::format("{:{}} | call(ns) | call2(ns) | check(ns)", "tool name", nameWidth);
533 std::cout << "\n" << header << std::endl;
534 std::cout << std::string(header.size(), '-') << std::endl;
535 for (auto& data : toolPerfData)
536 {
537 std::cout << std::format("{:{}} |", data.name, nameWidth);
538 if (data.timeCall)
539 std::cout << std::format("{:>9.0f} |", data.timeCall.value());
540 else
541 std::cout << " |";
542 if (data.timeCall2)
543 std::cout << std::format("{:>10.0f} |", data.timeCall2.value());
544 else
545 std::cout << " |";
546 if (data.timeCheck)
547 std::cout << std::format("{:>10.1f}", data.timeCheck.value());
548 std::cout << std::endl;
549 }
550 }
551 }
#define ANA_CHECK_THROW(EXP)
check whether the given expression was successful, throwing an exception on failure
int numberOfEvents()
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
the header information for the entire columnar data vector
the base class for all columnar components
this is a simple benchmarking helper class wrapping timers from std::chrono
Definition Benchmark.h:51
a class that interfaces an IColumnarTool to a ColumnVectorHeader
Tool for accessing xAOD files outside of Athena.
A relatively simple transient store for objects created in analysis.
Definition TStore.h:45
TestStore store
Definition TestStore.cxx:23
const std::string numberOfEventsName
the name used for the column containing the number of events
void renameContainers(IColumnarTool &tool, const std::vector< std::pair< std::string, std::string > > &renames)
rename containers in the columnar tool
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
the performance data for reading a single branch/column

Variable Documentation

◆ knownKeys

const std::unordered_map<std::string,SG::sgkey_t> columnar::TestUtils::knownKeys
static
Initial value:
=
{
{"AnalysisMuons", 0x3a6b126f},
{"AnalysisElectrons", 0x3902fec0},
{"AnalysisPhotons", 0x35d1472f},
{"AnalysisJets", 0x1afd1919},
{"egammaClusters", 0x15788d1f},
{"GSFConversionVertices", 0x1f3e85c9},
{"InDetTrackParticles", 0x1d3890db},
{"CombinedMuonTrackParticles", 0x340d9196},
{"ExtrapolatedMuonTrackParticles", 0x14e35e9f},
{"GSFTrackParticles", 0x2e42db0b},
{"InDetForwardTrackParticles", 0x143c6846},
{"MuonSpectrometerTrackParticles", 0x3993c8f3},
}

Definition at line 85 of file ColumnarPhysliteTest.cxx.

86 {
87 {"AnalysisMuons", 0x3a6b126f},
88 {"AnalysisElectrons", 0x3902fec0},
89 {"AnalysisPhotons", 0x35d1472f},
90 {"AnalysisJets", 0x1afd1919},
91 {"egammaClusters", 0x15788d1f},
92 {"GSFConversionVertices", 0x1f3e85c9},
93 {"InDetTrackParticles", 0x1d3890db},
94 {"CombinedMuonTrackParticles", 0x340d9196},
95 {"ExtrapolatedMuonTrackParticles", 0x14e35e9f},
96 {"GSFTrackParticles", 0x2e42db0b},
97 {"InDetForwardTrackParticles", 0x143c6846},
98 {"MuonSpectrometerTrackParticles", 0x3993c8f3},
99 };