20 #include "oneapi/tbb/task_arena.h" 21 #include "oneapi/tbb/task_group.h" 30 #include <sys/resource.h> 33 #include <system_error> 37 #include "boost/ptr_container/ptr_deque.hpp" 82 std::vector<std::string>
makeArgs(uint32_t
nEvents,
unsigned int nThreads, std::uint32_t
seed)
const;
84 void executeScript(std::vector<std::string>
const&
args,
int id,
bool isPost)
const;
92 const std::vector<std::string>
args_;
130 : scriptName_((iConfig.getParameter<
edm::FileInPath>(
"scriptName")).
fullPath()),
131 outputFile_(iConfig.getParameter<
std::
string>(
"outputFile")),
133 npars_(iConfig.getParameter<uint32_t>(
"numberOfParameters")),
134 nEvents_(iConfig.getUntrackedParameter<uint32_t>(
"nEvents")),
135 storeXML_(iConfig.getUntrackedParameter<
bool>(
"storeXML")),
136 generateConcurrently_(iConfig.getUntrackedParameter<
bool>(
"generateConcurrently")),
137 postGenerationCommand_(iConfig.getUntrackedParameter<
std::
vector<
std::
string>>(
"postGenerationCommand")) {
140 <<
"Problem with configuration: " <<
args_.size() <<
" script arguments given, expected " <<
npars_;
142 if (iConfig.
exists(
"nPartonMapping")) {
144 for (
auto&
cfg : processMap) {
145 unsigned processId(
cfg.getParameter<
unsigned>(
"idprup"));
149 if (orderStr ==
"LO")
151 else if (orderStr ==
"NLO")
155 <<
"Invalid order specification for process " << processId <<
": " << orderStr;
157 unsigned np(
cfg.getParameter<
unsigned>(
"np"));
163 xmlPutToken_ = produces<LHEXMLStringProduct, edm::Transition::BeginRun>(
"LHEScriptOutput");
181 <<
"No lhe event found in ExternalLHEProducer::produce(). " 182 <<
"The likely cause is that the lhe file contains fewer events than were requested, which is possible " 183 <<
"in case of phase space integration or uneweighting efficiency problems.";
186 std::unique_ptr<LHEEventProduct> product(
206 order = procDef.first;
208 }
catch (std::out_of_range&) {
210 <<
"Unexpected IDPRUP encountered: " <<
partonLevel_->getHEPEUP()->IDPRUP;
215 product->setNpLO(
np);
216 product->setNpNLO(-1);
219 product->setNpLO(-1);
220 product->setNpNLO(
np);
247 <<
"The ExternalLHEProducer module requires the RandomNumberGeneratorService\n" 248 "which is not present in the configuration file. You must add the service\n" 249 "in the configuration file if you want to run ExternalLHEProducer";
252 std::vector<std::string> infiles;
258 std::exception_ptr except;
259 std::atomic<char> exceptSet{0};
261 tbb::this_task_arena::isolate([
this, &except, &infiles, &exceptSet, nEventsAve, overflow,
seed]() {
262 tbb::task_group
group;
270 using namespace std::filesystem;
273 infiles[
t] =
out.native();
277 if (exceptSet.compare_exchange_strong(expected, 1)) {
278 except = std::current_exception();
286 if (exceptSet != 0) {
287 std::rethrow_exception(except);
290 infiles = std::vector<std::string>(1,
outputFile_);
300 edm::LogWarning(
"ExternalLHEProducer") << postcmd[0] <<
" is not a relative path. Run it as a shell command.";
312 using namespace std::filesystem;
317 std::ifstream instream(
file);
321 instream.seekg(0, instream.end);
322 int insize = instream.tellg();
323 instream.seekg(0, instream.beg);
324 p->fillCompressedContent(instream, 0.25 * insize);
337 unsigned int skip = 0;
338 reader_ = std::make_unique<lhef::LHEReader>(infiles,
skip);
349 if (std::getenv(
"VALIDATION_RUN") !=
nullptr) {
351 <<
"Event loop is over, but there are still lhe events to process, ignoring...";
354 <<
"Error in ExternalLHEProducer::endRunProduce(). " 355 <<
"Event loop is over, but there are still lhe events to process." 356 <<
"This could happen if lhe file contains more events than requested. This is never expected to happen.";
363 using namespace std::filesystem;
366 if (unlink(
out.c_str())) {
367 throw cms::Exception(
"OutputDeleteError") <<
"Unable to delete original script output file " <<
out 368 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
374 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
380 unsigned int nThreads,
381 std::uint32_t
seed)
const {
382 std::vector<std::string>
args;
393 for (
unsigned int iArg = 0; iArg <
args.size(); iArg++) {
394 LogDebug(
"LHEInputArgs") <<
"arg [" << iArg <<
"] = " <<
args[iArg];
408 if ((
dir = opendir(
"/proc/self/fd"))) {
410 while ((
dp = readdir(
dir)) !=
nullptr) {
411 if ((strcmp(
dp->d_name,
".") == 0) || (strcmp(
dp->d_name,
"..") == 0)) {
414 if (sscanf(
dp->d_name,
"%d", &
fd) != 1) {
430 for (
fd = 3;
fd < maxfd + 1;
fd++) {
442 int filedes[2], fd_flags;
449 if ((fd_flags = fcntl(filedes[1], F_GETFD,
NULL)) == -1) {
451 <<
"Failed to get pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
453 if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
455 <<
"Failed to set pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
458 unsigned int argc_pre = 0;
463 unsigned int argc = argc_pre +
args.size();
469 for (
unsigned int i = 0;
i <
args.size();
i++) {
479 using namespace std::filesystem;
483 create_directory(newDir, ec);
484 current_path(newDir, ec);
489 while ((
write(filedes[1], &rc,
sizeof(
int)) == -1) && (errno == EINTR)) {
495 for (
unsigned int i = 0;
i <
args.size() + 1;
i++) {
502 <<
"Unable to fork a child (errno=" << errno <<
", " << strerror(errno) <<
")";
507 while (((rc2 =
read(filedes[0], &rc,
sizeof(
int))) == -1) && (errno == EINTR)) {
510 if ((rc2 ==
sizeof(
int)) && rc) {
512 <<
"Failed to execute script (errno=" << rc <<
", " << strerror(rc) <<
")";
519 if (waitpid(pid, &
status, 0) < 0) {
520 if (errno == EINTR) {
524 <<
"Failed to read child status (errno=" << errno <<
", " << strerror(errno) <<
")";
527 if (WIFSIGNALED(
status)) {
528 throw cms::Exception(
"ExternalLHEProducer") <<
"Child exited due to signal " << WTERMSIG(
status) <<
".";
536 throw cms::Exception(
"ExternalLHEProducer") <<
"Child failed with exit code " << rc <<
".";
545 desc.setComment(
"Executes an external script and places its output file into an EDM collection");
550 desc.add<std::vector<std::string>>(
"args");
551 desc.add<uint32_t>(
"numberOfParameters");
552 desc.addUntracked<uint32_t>(
"nEvents");
553 desc.addUntracked<
bool>(
"storeXML",
false);
554 desc.addUntracked<
bool>(
"generateConcurrently",
false)
555 ->setComment(
"If true, run the script concurrently in separate processes.");
556 desc.addUntracked<std::vector<std::string>>(
"postGenerationCommand", std::vector<std::string>())
558 "Command to run after the generation script has completed. The first argument can be a relative path.");
561 nPartonMappingDesc.
add<
unsigned>(
"idprup");
563 nPartonMappingDesc.
add<
unsigned>(
"np");
564 desc.addVPSetOptional(
"nPartonMapping", nPartonMappingDesc);
570 std::unique_ptr<LHERunInfoProduct> retValue;
572 for (
auto const&
file : iFiles) {
573 unsigned int skip = 0;
574 std::vector<std::string> infiles(1,
file);
575 auto reader = std::make_unique<lhef::LHEReader>(infiles,
skip);
576 auto parton =
reader->next();
580 auto runInfo = parton->getRunInfo();
583 std::for_each(
runInfo->getHeaders().begin(),
586 std::for_each(
runInfo->getComments().begin(),
590 retValue = std::make_unique<LHERunInfoProduct>(
std::move(product));
612 newFileOpened =
false;
void beginRunProduce(edm::Run &run, edm::EventSetup const &es) override
void addHeader(const Header &header)
std::string fullPath() const
void addComment(const std::string &line)
void produce(edm::Event &, const edm::EventSetup &) override
bool exists(std::string const ¶meterName) const
checks if a parameter exists
void addWeight(const WGT &wgt)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
edm::EDPutTokenT< LHERunInfoProduct > beginRunPutToken_
edm::EDPutTokenT< LHEEventProduct > eventPutToken_
static std::string to_string(const XMLCh *ch)
void free(void *ptr) noexcept
std::unique_ptr< LHERunInfoProduct > generateRunInfo(std::vector< std::string > const &files) const
void addDefault(ParameterSetDescription const &psetDescription)
virtual std::uint32_t mySeed() const =0
edm::EDPutTokenT< LHEXMLStringProduct > xmlPutToken_
bool generateConcurrently_
std::unique_ptr< lhef::LHEReader > reader_
#define DEFINE_FWK_MODULE(type)
std::map< unsigned, std::pair< unsigned, unsigned > > nPartonMapping_
def pipe(cmdline, input=None)
ParameterDescriptionBase * add(U const &iLabel, T const &value)
int closeDescriptors(int preserve) const
void executeScript(std::vector< std::string > const &args, int id, bool isPost) const
const std::vector< std::string > args_
std::vector< std::string > makeArgs(uint32_t nEvents, unsigned int nThreads, std::uint32_t seed) const
std::string outputContents_
const std::vector< std::string > postGenerationCommand_
void addComment(const std::string &line)
void beginRun(edm::Run const &, edm::EventSetup const &) override
void preallocThreads(unsigned int) override
bool mergeProduct(const LHERunInfoProduct &other)
VParameterSet const & getParameterSetVector(std::string const &name) const
FileCloseSentry & operator=(const FileCloseSentry &)=delete
Log< level::Warning, false > LogWarning
ExternalLHEProducer(const edm::ParameterSet &iConfig)
std::shared_ptr< lhef::LHEEvent > partonLevel_
void endRun(edm::Run const &, edm::EventSetup const &) override