ATLAS Offline Software
Loading...
Searching...
No Matches
PepperConfig Namespace Reference

Functions

 _resolve_pepper_executable ()
 _resolve_data_path (exe)
 _split_ext (filename)
 run_pepper (process, nevents, seed, ecm, output="pepper.events.gz", batch_size=None, n_batches=None, extra_args=None)

Variables

 log = logging.getLogger("PepperConfig")
dict _EXT_MAP

Detailed Description

Driver that invokes the LCG-installed `pepper` binary from inside an
AthGeneration job.

This module exists because the pepper_kokkos package as shipped in LCG
needs three things wired up correctly before it will run:

1. The PEPPER_DATA_PATH env var must point at the process-data
   directory (the binary's compiled-in path is the build server's
   scratch dir and doesn't exist on cvmfs). The wrapper sets it
   automatically.

2. The output filename's extension governs the format. The pepper
   binary accepts `.lhef[.gz]`, `.hepmc3[.gz]`, `.hdf5`, and `.debug`.
   AthGeneration's Gen_tf.py post-job validator globs for `*.events*`
   (MadGraph/Powheg convention). We resolve the tension by accepting
   `.events.gz` (or `.events`) as the user-facing default: pepper is
   invoked with the equivalent `.lhef[.gz]` form, then symlinked back
   to the requested `.events.gz` name.

3. The binary deadlocks in Kokkos initialisation on CPU-only nodes,
   waiting for a CUDA device. Jobs MUST run on a GPU-equipped worker.

Function Documentation

◆ _resolve_data_path()

PepperConfig._resolve_data_path ( exe)
protected
Return the directory containing the Pepper process CSVs.

Tries (in order): PEPPER_DATA_PATH env var; the share/pepper/data
directory next to the binary (1.8.x layout); the share/pepper_data
directory next to the binary (1.1.x layout).

Definition at line 64 of file PepperConfig.py.

64def _resolve_data_path(exe):
65 """Return the directory containing the Pepper process CSVs.
66
67 Tries (in order): PEPPER_DATA_PATH env var; the share/pepper/data
68 directory next to the binary (1.8.x layout); the share/pepper_data
69 directory next to the binary (1.1.x layout).
70 """
71 candidate = os.environ.get("PEPPER_DATA_PATH")
72 if candidate and os.path.isfile(os.path.join(candidate, "2j.csv")):
73 return candidate
74
75 install_root = os.path.dirname(os.path.dirname(os.path.realpath(exe)))
76 for sub in ("share/pepper/data", "share/pepper_data"):
77 candidate = os.path.join(install_root, sub)
78 if os.path.isfile(os.path.join(candidate, "2j.csv")):
79 return candidate
80
81 raise RuntimeError(
82 "Could not locate Pepper's process-data directory. "
83 "Set PEPPER_DATA_PATH explicitly to the directory containing "
84 "2j.csv, z0j.csv, etc."
85 )
86
87

◆ _resolve_pepper_executable()

PepperConfig._resolve_pepper_executable ( )
protected
Return the absolute path to the `pepper` binary, or raise.

Definition at line 51 of file PepperConfig.py.

51def _resolve_pepper_executable():
52 """Return the absolute path to the `pepper` binary, or raise."""
53 exe = os.environ.get("PEPPER_EXECUTABLE") or shutil.which("pepper")
54 if not exe or not os.path.isfile(exe):
55 raise RuntimeError(
56 "Could not locate the `pepper` executable. "
57 "Either set PEPPER_EXECUTABLE, or ensure that an LCG view "
58 "containing pepper_kokkos is on PATH "
59 "(e.g. /cvmfs/sft.cern.ch/lcg/views/LCG_109a/x86_64-el9-gcc13-opt)."
60 )
61 return exe
62
63

◆ _split_ext()

PepperConfig._split_ext ( filename)
protected
Return (stem, longest matching extension) where the extension
is one of the keys in _EXT_MAP. Raises if no match.

Definition at line 88 of file PepperConfig.py.

88def _split_ext(filename):
89 """Return (stem, longest matching extension) where the extension
90 is one of the keys in _EXT_MAP. Raises if no match."""
91 for ext in sorted(_EXT_MAP.keys(), key=len, reverse=True):
92 if filename.endswith(ext):
93 return filename[:-len(ext)], ext
94 raise ValueError(
95 "Pepper output filename %r must end in one of: %s"
96 % (filename, ", ".join(sorted(_EXT_MAP.keys()))))
97
98

◆ run_pepper()

PepperConfig.run_pepper ( process,
nevents,
seed,
ecm,
output = "pepper.events.gz",
batch_size = None,
n_batches = None,
extra_args = None )
Invoke `pepper`, produce an event file, and return its path.

The default output is `.events.gz` to match the convention used by
AthGeneration's `Gen_tf.py` for upstream-generator input files
(`Pythia8_LHEF` and the transform's post-job validator both look
for `*.events*`). Internally we invoke pepper with the
corresponding `.lhef[.gz]` extension and create the `.events[.gz]`
name as a symlink.

Parameters
----------
process     : Pepper process shortcut, e.g. "ppjj", "ppz1j", "pptt".
nevents     : Approximate number of unweighted events wanted.
seed        : Random seed (typically runArgs.randomSeed).
ecm         : Centre-of-mass energy in GeV (typically runArgs.ecmEnergy).
output      : Output filename. Must end in one of .events[.gz],
              .lhef[.gz], .hepmc3[.gz], .hdf5, or .debug.
batch_size  : Pepper batch size. Defaults to min(nevents, 5000).
n_batches   : Number of batches. Defaults so that we usually
              overshoot the requested nevents after accounting for
              unweighting efficiency.
extra_args  : List of additional CLI args to pass through.

Returns
-------
The absolute path of the event file in $PWD.

Definition at line 99 of file PepperConfig.py.

106 extra_args=None):
107 """Invoke `pepper`, produce an event file, and return its path.
108
109 The default output is `.events.gz` to match the convention used by
110 AthGeneration's `Gen_tf.py` for upstream-generator input files
111 (`Pythia8_LHEF` and the transform's post-job validator both look
112 for `*.events*`). Internally we invoke pepper with the
113 corresponding `.lhef[.gz]` extension and create the `.events[.gz]`
114 name as a symlink.
115
116 Parameters
117 ----------
118 process : Pepper process shortcut, e.g. "ppjj", "ppz1j", "pptt".
119 nevents : Approximate number of unweighted events wanted.
120 seed : Random seed (typically runArgs.randomSeed).
121 ecm : Centre-of-mass energy in GeV (typically runArgs.ecmEnergy).
122 output : Output filename. Must end in one of .events[.gz],
123 .lhef[.gz], .hepmc3[.gz], .hdf5, or .debug.
124 batch_size : Pepper batch size. Defaults to min(nevents, 5000).
125 n_batches : Number of batches. Defaults so that we usually
126 overshoot the requested nevents after accounting for
127 unweighting efficiency.
128 extra_args : List of additional CLI args to pass through.
129
130 Returns
131 -------
132 The absolute path of the event file in $PWD.
133 """
134 exe = _resolve_pepper_executable()
135 data = _resolve_data_path(exe)
136
137 stem, user_ext = _split_ext(output)
138 pepper_ext = _EXT_MAP[user_ext]
139 pepper_output = stem + pepper_ext
140
141 if batch_size is None:
142 batch_size = min(nevents, 5000)
143 if n_batches is None:
144 # Unweighting efficiency is process-dependent; pad by 2x so
145 # we usually overshoot rather than undershoot.
146 n_batches = max(1, (2 * nevents + batch_size - 1) // batch_size)
147
148 cmd = [exe,
149 "--process", str(process),
150 "--collision-energy", str(ecm),
151 "--seed", str(seed),
152 "--batch-size", str(batch_size),
153 "--n-batches", str(n_batches),
154 "--output", pepper_output]
155 if extra_args:
156 cmd += list(extra_args)
157
158 env = os.environ.copy()
159 env["PEPPER_DATA_PATH"] = data
160 # Sensible OpenMP defaults so Kokkos doesn't warn at startup.
161 env.setdefault("OMP_PROC_BIND", "spread")
162 env.setdefault("OMP_PLACES", "threads")
163
164 log.info("PEPPER_DATA_PATH = %s", data)
165 log.info("Pepper command: %s", " ".join(cmd))
166
167 rc = subprocess.call(cmd, env=env)
168 if rc != 0:
169 raise RuntimeError("pepper exited with rc=%d" % rc)
170 if not os.path.isfile(pepper_output):
171 raise RuntimeError("pepper succeeded but %s is missing" % pepper_output)
172
173 # If user requested a name different from what pepper produces
174 # (typical: user asked for .events.gz; pepper made .lhef.gz),
175 # link the user-facing name to the actual file.
176 if output != pepper_output:
177 if os.path.lexists(output):
178 os.remove(output)
179 os.symlink(os.path.basename(pepper_output), output)
180 log.info("Linked %s -> %s", output, pepper_output)
181
182 return os.path.abspath(output)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41

Variable Documentation

◆ _EXT_MAP

dict PepperConfig._EXT_MAP
protected
Initial value:
1= {
2 ".events.gz": ".lhef.gz",
3 ".events": ".lhef",
4 # Pass-through: pepper recognises these natively.
5 ".lhef.gz": ".lhef.gz",
6 ".lhef": ".lhef",
7 ".hepmc3.gz": ".hepmc3.gz",
8 ".hepmc3": ".hepmc3",
9 ".hdf5": ".hdf5",
10 ".debug": ".debug",
11}

Definition at line 38 of file PepperConfig.py.

◆ log

PepperConfig.log = logging.getLogger("PepperConfig")

Definition at line 31 of file PepperConfig.py.