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

HybridGenerator: Asyncronous + parallel event generation #13788

Merged
merged 1 commit into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions Generators/include/Generators/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class Generator : public FairGenerator
/** lorentz boost data members **/
Double_t mBoost;

// a unique generator instance counter
// this can be used to make sure no two generator instances have the same seed etc.
static std::atomic<int> InstanceCounter;
int mThisInstanceID = 0;

private:
void updateSubGeneratorInformation(o2::dataformats::MCEventHeader* header) const;

Expand Down
1 change: 1 addition & 0 deletions Generators/include/Generators/GeneratorExternalParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct GeneratorExternalParam : public o2::conf::ConfigurableParamHelper<Generat
struct ExternalGenConfig {
std::string fileName = "";
std::string funcName = "";
std::string iniFile = ""; // if ini file is given, the configuration will be taken from this and the other 2 fields neglected
};

} // end namespace eventgen
Expand Down
36 changes: 34 additions & 2 deletions Generators/include/Generators/GeneratorHybrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
#include <rapidjson/writer.h>
#include "TBufferJSON.h"

#include <tbb/concurrent_queue.h>
#include <tbb/task_arena.h>
#include <iostream>
#include <thread>
#include <atomic>

namespace o2
{
namespace eventgen
Expand All @@ -50,25 +56,29 @@ class GeneratorHybrid : public Generator
public:
GeneratorHybrid() = default;
GeneratorHybrid(const std::string& inputgens);
~GeneratorHybrid() = default;
~GeneratorHybrid();

Bool_t Init() override;
Bool_t generateEvent() override;
Bool_t importParticles() override;

void setNEvents(int n) { mNEvents = n; }

Bool_t parseJSON(const std::string& path);
template <typename T>
std::string jsonValueToString(const T& value);

private:
o2::eventgen::Generator* currentgen = nullptr;
std::vector<std::unique_ptr<o2::eventgen::Generator>> gens;
std::vector<std::shared_ptr<o2::eventgen::Generator>> gens;
const std::vector<std::string> generatorNames = {"extkinO2", "evtpool", "boxgen", "external", "hepmc", "pythia8", "pythia8pp", "pythia8hi", "pythia8hf", "pythia8powheg"};
std::vector<std::string> mInputGens;
std::vector<std::string> mGens;
std::vector<std::string> mConfigs;
std::vector<std::string> mConfsPythia8;

std::vector<bool> mGenIsInitialized;

// Parameters configurations
std::vector<std::unique_ptr<o2::eventgen::BoxGenConfig>> mBoxGenConfigs;
std::vector<std::unique_ptr<o2::eventgen::Pythia8GenConfig>> mPythia8GenConfigs;
Expand All @@ -84,6 +94,28 @@ class GeneratorHybrid : public Generator
int mseqCounter = 0;
int mCurrentFraction = 0;
int mIndex = 0;
int mEventCounter = 0;
int mTasksStarted = 0;

// Create a task arena with a specified number of threads
std::thread mTBBTaskPoolRunner;
tbb::concurrent_bounded_queue<int> mInputTaskQueue;
std::vector<tbb::concurrent_bounded_queue<int>> mResultQueue;
tbb::task_arena mTaskArena;
std::atomic<bool> mStopFlag;
bool mIsInitialized = false;

int mNEvents = -1; // the number of events to be done, if known (helps initiating cleanup)

enum class GenMode {
kSeq,
kParallel
};

// hybrid gen operation mode - should be either 'sequential' or 'parallel'
// parallel means that we have clones of the same generator collaborating on event generation
// sequential means that events will be produced in the order given by fractions; async processing is still happening
GenMode mGenerationMode = GenMode::kSeq; //!
};

} // namespace eventgen
Expand Down
1 change: 1 addition & 0 deletions Generators/include/Generators/GeneratorHybridParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace eventgen
struct GeneratorHybridParam : public o2::conf::ConfigurableParamHelper<GeneratorHybridParam> {
std::string configFile = ""; // JSON configuration file for the generators
bool randomize = false; // randomize the order of the generators, if not generator using fractions
int num_workers = 1; // number of threads available for asyn/parallel event generation
O2ParamDef(GeneratorHybridParam, "GeneratorHybrid");
};

Expand Down
3 changes: 3 additions & 0 deletions Generators/include/Generators/GeneratorPythia8.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ class GeneratorPythia8 : public Generator
// Value of -1 means unitialized; 0 will be time-dependent and values >1 <= MAX_SEED concrete reproducible seeding
Pythia8GenConfig mGenConfig; // configuration object

static std::atomic<int> Pythia8InstanceCounter;
int mThisPythia8InstanceID = 0;

constexpr static long MAX_SEED = 900000000;

ClassDefOverride(GeneratorPythia8, 1);
Expand Down
6 changes: 6 additions & 0 deletions Generators/src/Generator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ namespace o2
namespace eventgen
{

std::atomic<int> Generator::InstanceCounter{0};

/*****************************************************************/
/*****************************************************************/

Generator::Generator() : FairGenerator("ALICEo2", "ALICEo2 Generator"),
mBoost(0.)
{
/** default constructor **/
mThisInstanceID = Generator::InstanceCounter;
Generator::InstanceCounter++;
}

/*****************************************************************/
Expand All @@ -43,6 +47,8 @@ Generator::Generator(const Char_t* name, const Char_t* title) : FairGenerator(na
mBoost(0.)
{
/** constructor **/
mThisInstanceID = Generator::InstanceCounter;
Generator::InstanceCounter++;
}

/*****************************************************************/
Expand Down
1 change: 1 addition & 0 deletions Generators/src/GeneratorFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair
return;
}
auto hybrid = new o2::eventgen::GeneratorHybrid(config);
hybrid->setNEvents(conf.getNEvents());
primGen->AddGenerator(hybrid);
#endif
} else {
Expand Down
Loading
Loading