Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support running multithreaded: Add an IOSvc, an algorithm for reading and writing for functionals in k4FWCore #173

Merged
merged 127 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 117 commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
a0bf553
Add an IOSvc, an algorithm for reading and writing
jmcarcell Nov 14, 2023
462af5f
Working example with new Consumers
jmcarcell Mar 25, 2024
64026ef
Make changes, everything working except reading from multiple files
jmcarcell Mar 25, 2024
2a91804
Add fixes to read multiple collections
jmcarcell Dec 30, 2023
e434386
Fix tests
jmcarcell Dec 31, 2023
9428e4c
Add another test
jmcarcell Dec 31, 2023
5e7368c
Add changes to make multithreading reading and writing work
jmcarcell Jan 18, 2024
2cb92bf
Add changes to read multiple collections
jmcarcell Feb 4, 2024
6b727d3
Add functionality to read multiple collections
jmcarcell Feb 5, 2024
8394e2a
Change to ROOTReader and ROOTWriter
jmcarcell Feb 8, 2024
b609670
Add reading multiple sets of multiple collections
jmcarcell Feb 8, 2024
a237f64
Add a new version of the consumer
jmcarcell Feb 11, 2024
3426bd5
Add the old version of the consumer
jmcarcell Feb 12, 2024
b57f985
Add reading maps of edm4hep collections
jmcarcell Feb 12, 2024
35a3255
Make some clean up in the consumer
jmcarcell Feb 12, 2024
59170f0
Add the python folder
jmcarcell Feb 12, 2024
98099f7
Delete another unused test file
jmcarcell Feb 12, 2024
f71df09
Fix a few tests by making all the parameters lists
jmcarcell Feb 12, 2024
327d252
Add a new transformer
jmcarcell Feb 12, 2024
2459397
Fix the producers
jmcarcell Feb 13, 2024
eaeebb2
Make all properties not be lists
jmcarcell Feb 13, 2024
6469a62
Add a hash function for hidden properties
jmcarcell Feb 13, 2024
ec210e6
Simplify and clean up the consumer
jmcarcell Feb 14, 2024
2f8884c
Fix tests to not only work with lists
jmcarcell Feb 14, 2024
00664a5
Add reading and writing from any to any in the transformer
jmcarcell Feb 15, 2024
1c87a64
Use ROOTWriter
jmcarcell Feb 15, 2024
7ba4419
Format
jmcarcell Feb 15, 2024
d1b2770
Comment out the RNTuple readers and writers
jmcarcell Feb 15, 2024
21d5b3b
Use PROJECT_NAME
jmcarcell Feb 16, 2024
d617e88
Change the order of the python directory for tests
jmcarcell Feb 16, 2024
926f7c2
Install the python files to one of the build directories
jmcarcell Feb 16, 2024
2b05dda
Use CMAKE_CURRENT_LIST_DIR for this test to make dependent tests pass
jmcarcell Feb 16, 2024
783debb
Fix syntax
jmcarcell Feb 16, 2024
cc07d96
Use getAvailableCollections
jmcarcell Feb 16, 2024
1e25926
Fix test
jmcarcell Feb 16, 2024
d261c2b
Fix tests
jmcarcell Feb 16, 2024
f01c0eb
Don't install
jmcarcell Feb 16, 2024
365cfda
Comment out
jmcarcell Feb 16, 2024
be277ba
Copy some files for tests
jmcarcell Feb 16, 2024
4d97dbc
Change order
jmcarcell Feb 16, 2024
18778dd
Try this
jmcarcell Feb 16, 2024
e06e489
Format
jmcarcell Feb 16, 2024
72496cb
Remove a couple of files
jmcarcell Feb 16, 2024
2686d8b
More format
jmcarcell Feb 16, 2024
9307ba8
Format
jmcarcell Feb 16, 2024
62aaa44
Format
jmcarcell Feb 16, 2024
cac24cb
Add the genConfDir that seems to be necessary sometimes
jmcarcell Feb 16, 2024
ee4519e
Improve test command and test output when it fails
jmcarcell Feb 16, 2024
487c2a6
Don't try to create any directories for inputs
jmcarcell Feb 17, 2024
9ae5f73
Remove info message
jmcarcell Feb 17, 2024
f0bb6e0
Use a SmartIF for the HiveWhiteBoard instead of a ServiceHandle
jmcarcell Feb 17, 2024
24db3a4
Add a sequencer for writing
jmcarcell Feb 17, 2024
cb92395
Remove brackets
jmcarcell Feb 21, 2024
5954d05
Format
jmcarcell Feb 22, 2024
e27742a
Format
jmcarcell Feb 29, 2024
0b15c1a
Delete old files and remove debugging warnings
jmcarcell Mar 5, 2024
dfef5ae
Fix a few tests and add some comments
jmcarcell Mar 5, 2024
ccf4ff2
Change a few imports
jmcarcell Mar 5, 2024
8dbcaa2
Add a test for writing 0 collections
jmcarcell Mar 5, 2024
b01fa5d
Fix warning
jmcarcell Mar 5, 2024
6ac240d
Fix test
jmcarcell Mar 6, 2024
446ccb6
Remove old file
jmcarcell Mar 6, 2024
f9b0bad
Update the transformers not to use std::shared_ptr in the output
jmcarcell Mar 8, 2024
2062d98
Update the consumer not to use shared_ptr and use references instead
jmcarcell Mar 8, 2024
6154232
Format
jmcarcell Mar 8, 2024
b7ab80c
References should be const
jmcarcell Mar 8, 2024
624158e
Enforce references being const
jmcarcell Mar 8, 2024
a9f5cec
Modify the transformer not to use std::shared_ptr in the inputs
jmcarcell Mar 8, 2024
f0d5dd6
Fix a few includes
jmcarcell Mar 8, 2024
f23ad30
Move readMapInputs to FunctionalUtils.h
jmcarcell Mar 8, 2024
7f68c31
Clean up and remove ExtractInnerType
jmcarcell Mar 8, 2024
6f4d0bf
Formatting and clean up
jmcarcell Mar 8, 2024
70ef4a8
Use the new reader and writer
jmcarcell Mar 8, 2024
f009f3a
Fix the FunctionalMemory test as it was intended to be (no IO)
jmcarcell Mar 8, 2024
5074526
Clean up includes and use k4FWCore::frameLocation
jmcarcell Mar 8, 2024
40b1b3f
Move the destructor comment, use .reset() and std::make_shared
jmcarcell Mar 8, 2024
576a257
Clean up and fix a test
jmcarcell Apr 23, 2024
7299916
Fix writing an arbitrary number of collections
jmcarcell Mar 10, 2024
a8335d1
Create all the needed data handles for the consumer
jmcarcell Mar 13, 2024
4ade0f3
Create the right handles when using the transformer
jmcarcell Mar 13, 2024
70099c7
Remove remaining GaudiAlg headers
jmcarcell Mar 25, 2024
01d6751
Make inputs and outputs lists
jmcarcell Mar 25, 2024
9de8b81
Add a few comments and a requirement on is_map_like
jmcarcell Mar 27, 2024
dbc1b35
Add asserts to have error messages when using a disallowed type
jmcarcell Mar 27, 2024
821b8f3
Check the services interfaces in IOSvc.cpp
jmcarcell Apr 2, 2024
42551fd
Add Service::initialize in IOSvc.cpp
jmcarcell Apr 2, 2024
8b7a162
Fix Service::initialize and clean up template functions
jmcarcell Apr 2, 2024
e56f68f
Apply suggestions from code review
jmcarcell Apr 19, 2024
0256dad
Apply suggestions for Writer.cpp
jmcarcell Apr 19, 2024
197db77
Allow combining functionals together with old algorithms
jmcarcell Apr 5, 2024
7029ffd
Remove unused ctx
jmcarcell Apr 15, 2024
97b1c3c
Fix typo
jmcarcell Apr 19, 2024
d9a58e7
Address a few comments in the PR
jmcarcell Apr 19, 2024
9b1cf05
Add error when a frame can't be pushed
jmcarcell Apr 19, 2024
35cbb47
Fix properties docstrings
jmcarcell Apr 19, 2024
797dfe3
Use isMapToCollLike_v
jmcarcell Apr 19, 2024
be69179
Return StatusCode::FAILURE instead of throwing
jmcarcell Apr 19, 2024
936638e
Add an error message
jmcarcell Apr 19, 2024
d6de2e2
Format a few files
jmcarcell Apr 19, 2024
9357347
Do a bit of cleanup and small fixes
jmcarcell Apr 23, 2024
ad7b8c9
Add a few comments to the Transformer
jmcarcell Apr 23, 2024
fc5d25c
Open a file to get the collections before running
jmcarcell Apr 23, 2024
a40f42e
Change one test
jmcarcell Apr 23, 2024
c14b230
Remove the remaining GaudiAlgs
jmcarcell Apr 23, 2024
4f7433b
Change EvtDataSvc to EventDataSvc
jmcarcell Apr 25, 2024
ade9bbd
Add missing test
jmcarcell Apr 25, 2024
11e68e3
Fix list of tests
jmcarcell Apr 25, 2024
969672a
Fix test (finally)
jmcarcell Apr 26, 2024
4c04e8f
Fix style
jmcarcell Apr 26, 2024
3a4e216
Fix parrallel running with a Sequencer, add tests and clean up
jmcarcell Apr 29, 2024
3765ea2
Add comments in the python files
jmcarcell Apr 29, 2024
8897c20
Bring back the output from a test
jmcarcell Apr 29, 2024
adc3d68
Add new line
jmcarcell Apr 29, 2024
12ea14f
Try to fix failing test
jmcarcell Apr 29, 2024
7dd3055
Clean up the Writer and add comments
jmcarcell Apr 29, 2024
1c4690f
Fix style and clean up
jmcarcell Apr 29, 2024
312725d
Have the runFunctionalMix tests run with a single steering file
jmcarcell May 15, 2024
cd6b938
Use ShortCircuit=False
jmcarcell May 21, 2024
663b097
Fix typo
jmcarcell May 21, 2024
8c6893e
Use emplace_back
jmcarcell May 21, 2024
f5fdcf3
Remove some comments
jmcarcell May 21, 2024
1e8d0cc
Use isReEntrant for the Writer
jmcarcell May 21, 2024
e796ac3
Fix pre-commit
jmcarcell May 21, 2024
dc6e736
Fix workflow files
jmcarcell May 21, 2024
6409c2f
Use alma9
jmcarcell May 21, 2024
e073c00
Go back to centos7
jmcarcell May 21, 2024
afd2856
Fix path
jmcarcell May 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ endif()

add_subdirectory(k4FWCore)
add_subdirectory(k4Interface)
add_subdirectory(python)
if(BUILD_TESTING)
add_subdirectory(test/k4FWCoreTest)
endif()


option(ENABLE_CPACK "Whether or not to use cpack config" OFF)
if(ENABLE_CPACK)
include(cmake/${PROJECT_NAME}CPack.cmake)
Expand Down
6 changes: 6 additions & 0 deletions k4FWCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/k4FWCore/python/k4FWCore
${CMAKE_CURRENT_BINARY_DIR}/genConfDir/k4FWCore)

# This is needed to overwrite the __init__.py, see a long comment in the
# CMakeLists.txt in the test folder
add_custom_command(TARGET k4FWCorePlugins POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${PROJECT_SOURCE_DIR}/python/k4FWCore/__init__.py ${PROJECT_BINARY_DIR}/k4FWCore/genConfDir/k4FWCore/__init__.py)
57 changes: 57 additions & 0 deletions k4FWCore/components/IIOSvc.h
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2014-2024 Key4hep-Project.
*
* This file is part of Key4hep.
* See https://key4hep.github.io/key4hep-doc/ for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FWCORE_IIOSVC_H
#define FWCORE_IIOSVC_H

#include "GaudiKernel/IInterface.h"

#include "podio/CollectionBase.h"
#include "podio/ROOTWriter.h"

#include <memory>
#include <vector>

/**
* The interface implemented by any class making IO and reading RawEvent Data
*/
class IIOSvc : virtual public IInterface {
public:
struct EndOfInput : std::logic_error {
EndOfInput() : logic_error("Reached end of input while more data were expected"){};
};

public:
/// InterfaceID
DeclareInterfaceID(IIOSvc, 1, 0);

/**
* @brief Read the next event from the input file
* @return A tuple containing the collections read, the collection names and the frame that owns the collections
*/
virtual std::tuple<std::vector<std::shared_ptr<podio::CollectionBase>>, std::vector<std::string>, podio::Frame>
next() = 0;
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
virtual std::shared_ptr<std::vector<std::string>> getCollectionNames() const = 0;

virtual std::shared_ptr<podio::ROOTWriter> getWriter() = 0;
virtual void deleteWriter() = 0;
virtual void deleteReader() = 0;
virtual bool checkIfWriteCollection(const std::string& collName) = 0;
};

#endif
159 changes: 159 additions & 0 deletions k4FWCore/components/IOSvc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2014-2024 Key4hep-Project.
*
* This file is part of Key4hep.
* See https://key4hep.github.io/key4hep-doc/ for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "IOSvc.h"

#include "podio/Frame.h"
#include "podio/FrameCategories.h"

#include "k4FWCore/FunctionalUtils.h"
#include "k4FWCore/KeepDropSwitch.h"

#include "GaudiKernel/AnyDataWrapper.h"
#include "GaudiKernel/IEventProcessor.h"

#include <mutex>
#include <tuple>

StatusCode IOSvc::initialize() {
StatusCode sc = Service::initialize();
if (sc.isFailure()) {
error() << "Unable to initialize base class Service." << endmsg;
return sc;
}
if (!m_readingFileNames.empty()) {
m_reader = std::make_unique<podio::ROOTReader>();
try {
m_reader->openFiles(m_readingFileNames);
} catch (std::runtime_error& e) {
error() << "Error when opening files: " << e.what() << endmsg;
return StatusCode::FAILURE;
}
m_entries = m_reader->getEntries(podio::Category::Event);
}

m_switch = KeepDropSwitch(m_outputCommands);

m_incidentSvc = service("IncidentSvc");
if (!m_incidentSvc) {
error() << "Unable to locate IIncidentSvc interface" << endmsg;
return StatusCode::FAILURE;
}
m_incidentSvc->addListener(this, IncidentType::EndEvent);

m_dataSvc = service("EventDataSvc");
if (!m_dataSvc) {
error() << "Unable to locate the EventDataSvc" << endmsg;
return StatusCode::FAILURE;
}

m_hiveWhiteBoard = service("EventDataSvc");
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved

return StatusCode::SUCCESS;
}

StatusCode IOSvc::finalize() { return Service::finalize(); }

std::tuple<std::vector<std::shared_ptr<podio::CollectionBase>>, std::vector<std::string>, podio::Frame> IOSvc::next() {
podio::Frame frame;
{
std::scoped_lock<std::mutex> lock(m_changeBufferLock);
info() << "m_nextEntry = " << m_nextEntry << " m_entries = " << m_entries << endmsg;
if (m_nextEntry < m_entries) {
frame = podio::Frame(std::move(m_reader->readEntry(podio::Category::Event, m_nextEntry)));
} else {
return std::make_tuple(std::vector<std::shared_ptr<podio::CollectionBase>>(), std::vector<std::string>(),
std::move(frame));
}
m_nextEntry++;
if (m_collectionNames.empty()) {
m_collectionNames = frame.getAvailableCollections();
}
}

if (m_nextEntry >= m_entries) {
// if (true) {
auto ep = serviceLocator()->as<IEventProcessor>();
StatusCode sc = ep->stopRun();
if (sc.isFailure()) {
error() << "Error when stopping run" << endmsg;
throw GaudiException("Error when stopping run", name(), StatusCode::FAILURE);
}
info() << "m_nextEntry = " << m_nextEntry << " m_entries = " << m_entries << endmsg;
}

std::vector<std::shared_ptr<podio::CollectionBase>> collections;

for (const auto& name : m_collectionNames) {
auto ptr = const_cast<podio::CollectionBase*>(frame.get(name));
collections.push_back(std::shared_ptr<podio::CollectionBase>(ptr));
}

return std::make_tuple(collections, m_collectionNames, std::move(frame));
}

// After every event if there is still a frame in the TES
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
// that means it hasn't been written so the collections inside the Frame
// should be removed so that they are deleted when the Frame is deleted
// and not deleted when clearing the store
void IOSvc::handle(const Incident& incident) {
StatusCode code;
if (m_hiveWhiteBoard) {
if (!incident.context().valid()) {
info() << "No context found in IOSvc" << endmsg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
info() << "No context found in IOSvc" << endmsg;
info() << "No context found in incident" << endmsg;

Or why IOSvc?

return;
}
debug() << "Setting store to " << incident.context().slot() << endmsg;
code = m_hiveWhiteBoard->selectStore(incident.context().slot());
if (code.isFailure()) {
error() << "Error when setting store" << endmsg;
throw GaudiException("Error when setting store", name(), StatusCode::FAILURE);
}
}
DataObject* p;
code = m_dataSvc->retrieveObject("/Event" + k4FWCore::frameLocation, p);
if (code.isFailure()) {
return;
}

auto frame = dynamic_cast<AnyDataWrapper<podio::Frame>*>(p);
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
if (!frame) {
error() << "Expected Frame in " << k4FWCore::frameLocation << " but there was something else" << endmsg;
return;
}
for (const auto& coll : frame->getData().getAvailableCollections()) {
DataObject* collPtr;
code = m_dataSvc->retrieveObject("/Event/" + coll, collPtr);
if (code.isSuccess()) {
debug() << "Removing the collection: " << coll << " from the store" << endmsg;
code = m_dataSvc->unregisterObject(collPtr);
}
// else {
// info() << "Collection not found: " << coll << endmsg;
// }
}
}

void IOSvc::setReadingCollectionNames(const std::vector<std::string>& names) { m_collectionNames = names; }

void IOSvc::setReadingFileNames(const std::vector<std::string>& names) { m_readingFileNames = names; }

bool IOSvc::checkIfWriteCollection(const std::string& collName) { return m_switch.isOn(collName); }

DECLARE_COMPONENT(IOSvc)
96 changes: 96 additions & 0 deletions k4FWCore/components/IOSvc.h
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2014-2024 Key4hep-Project.
*
* This file is part of Key4hep.
* See https://key4hep.github.io/key4hep-doc/ for further info.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FWCORE_IOSVC_H
#define FWCORE_IOSVC_H

#include "Gaudi/Property.h"
#include "GaudiKernel/IDataProviderSvc.h"
#include "GaudiKernel/IHiveWhiteBoard.h"
#include "GaudiKernel/IIncidentListener.h"
#include "GaudiKernel/IIncidentSvc.h"
#include "GaudiKernel/Service.h"

#include "podio/ROOTReader.h"
#include "podio/ROOTWriter.h"

#include "IIOSvc.h"
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
#include "k4FWCore/KeepDropSwitch.h"

#include <string>
#include <vector>

class IOSvc : public extends<Service, IIOSvc, IIncidentListener> {
using extends::extends;

public:
~IOSvc() override = default;

StatusCode initialize() override;
StatusCode finalize() override;

std::tuple<std::vector<std::shared_ptr<podio::CollectionBase>>, std::vector<std::string>, podio::Frame> next()
override;

std::shared_ptr<std::vector<std::string>> getCollectionNames() const override {
return std::make_shared<std::vector<std::string>>(m_collectionNames);
}

void setReadingCollectionNames(const std::vector<std::string>& names);
void setReadingFileNames(const std::vector<std::string>& names);

protected:
Gaudi::Property<std::vector<std::string>> m_collectionNames{
this, "CollectionNames", {}, "List of collections to read"};
Gaudi::Property<std::vector<std::string>> m_readingFileNames{this, "input", {}, "List of files to read"};
Gaudi::Property<std::string> m_writingFileName{this, "output", {}, "List of files to write output to"};
Gaudi::Property<std::vector<std::string>> m_outputCommands{
this, "outputCommands", {"keep *"}, "A set of commands to declare which collections to keep or drop."};
Gaudi::Property<std::string> m_inputType{this, "ioType", "ROOT", "Type of input file (ROOT, RNTuple)"};

std::mutex m_changeBufferLock;

KeepDropSwitch m_switch;

std::unique_ptr<podio::ROOTReader> m_reader{nullptr};
std::shared_ptr<podio::ROOTWriter> m_writer{nullptr};

std::shared_ptr<podio::ROOTWriter> getWriter() override {
if (!m_writer) {
m_writer = std::make_shared<podio::ROOTWriter>(m_writingFileName.value());
}
return m_writer;
}

// Gaudi doesn't always run the destructor of the Services so we have to
// manually ask for the writer to be deleted so it will call finish()
void deleteWriter() override { m_writer.reset(); }
void deleteReader() override { m_reader.reset(); }

SmartIF<IDataProviderSvc> m_dataSvc;
SmartIF<IIncidentSvc> m_incidentSvc;
SmartIF<IHiveWhiteBoard> m_hiveWhiteBoard;
void handle(const Incident& incident) override;

int m_entries{0};
int m_nextEntry{0};

bool checkIfWriteCollection(const std::string& collName) override;
};

#endif
Loading
Loading