CMS 3D CMS Logo

MkBuilder.cc
Go to the documentation of this file.
1 #include <memory>
2 #include <limits>
3 #include <algorithm>
4 
6 
10 
11 #include "Pool.h"
12 #include "CandCloner.h"
13 #include "FindingFoos.h"
14 #include "MkFitter.h"
15 #include "MkFinder.h"
16 
17 #ifdef MKFIT_STANDALONE
19 #endif
20 
21 //#define DEBUG
22 #include "Debug.h"
23 //#define DEBUG_FINAL_FIT
24 
25 #include "oneapi/tbb/parallel_for.h"
26 #include "oneapi/tbb/parallel_for_each.h"
27 
28 namespace mkfit {
29 
30  //==============================================================================
31  // Execution context -- Pools of helper objects
32  //==============================================================================
33 
35  ExecutionContext() = default;
36  ~ExecutionContext() = default;
37 
41 
42  void populate(int n_thr) {
43  m_cloners.populate(n_thr - m_cloners.size());
44  m_fitters.populate(n_thr - m_fitters.size());
45  m_finders.populate(n_thr - m_finders.size());
46  }
47 
48  void clear() {
49  m_cloners.clear();
50  m_fitters.clear();
51  m_finders.clear();
52  }
53  };
54 
56 
57 } // end namespace mkfit
58 
59 //------------------------------------------------------------------------------
60 
61 namespace {
62  using namespace mkfit;
63 
64  // Range of indices processed within one iteration of a TBB parallel_for.
65  struct RangeOfSeedIndices {
66  int m_rng_beg, m_rng_end;
67  int m_beg, m_end;
68 
69  RangeOfSeedIndices(int rb, int re) : m_rng_beg(rb), m_rng_end(re) { reset(); }
70 
71  void reset() {
72  m_end = m_rng_beg;
73  next_chunk();
74  }
75 
76  bool valid() const { return m_beg < m_rng_end; }
77 
78  int n_proc() const { return m_end - m_beg; }
79 
80  void next_chunk() {
81  m_beg = m_end;
82  m_end = std::min(m_end + NN, m_rng_end);
83  }
84 
85  RangeOfSeedIndices &operator++() {
86  next_chunk();
87  return *this;
88  }
89  };
90 
91  // Region of seed indices processed in a single TBB parallel for.
92  struct RegionOfSeedIndices {
93  int m_reg_beg, m_reg_end, m_vec_cnt;
94 
95  RegionOfSeedIndices(const std::vector<int> &seedEtaSeparators, int region) {
96  m_reg_beg = (region == 0) ? 0 : seedEtaSeparators[region - 1];
97  m_reg_end = seedEtaSeparators[region];
98  m_vec_cnt = (m_reg_end - m_reg_beg + NN - 1) / NN;
99  }
100 
101  int count() const { return m_reg_end - m_reg_beg; }
102 
103  tbb::blocked_range<int> tbb_blk_rng_std(int thr_hint = -1) const {
104  if (thr_hint < 0)
105  thr_hint = Config::numSeedsPerTask;
106  return tbb::blocked_range<int>(m_reg_beg, m_reg_end, thr_hint);
107  }
108 
109  tbb::blocked_range<int> tbb_blk_rng_vec() const {
110  return tbb::blocked_range<int>(0, m_vec_cnt, std::max(1, Config::numSeedsPerTask / NN));
111  }
112 
113  RangeOfSeedIndices seed_rng(const tbb::blocked_range<int> &i) const {
114  return RangeOfSeedIndices(m_reg_beg + NN * i.begin(), std::min(m_reg_beg + NN * i.end(), m_reg_end));
115  }
116  };
117 
118 #ifdef DEBUG
119  void pre_prop_print(int ilay, MkBase *fir) {
120  const float pt = 1.f / fir->getPar(0, 0, 3);
121  std::cout << "propagate to lay=" << ilay << " start from x=" << fir->getPar(0, 0, 0)
122  << " y=" << fir->getPar(0, 0, 1) << " z=" << fir->getPar(0, 0, 2)
123  << " r=" << getHypot(fir->getPar(0, 0, 0), fir->getPar(0, 0, 1))
124  << " px=" << pt * std::cos(fir->getPar(0, 0, 4)) << " py=" << pt * std::sin(fir->getPar(0, 0, 4))
125  << " pz=" << pt / std::tan(fir->getPar(0, 0, 5)) << " pT=" << pt << std::endl;
126  }
127 
128  void post_prop_print(int ilay, MkBase *fir) {
129  std::cout << "propagate to lay=" << ilay << " arrive at x=" << fir->getPar(0, 1, 0) << " y=" << fir->getPar(0, 1, 1)
130  << " z=" << fir->getPar(0, 1, 2) << " r=" << getHypot(fir->getPar(0, 1, 0), fir->getPar(0, 1, 1))
131  << std::endl;
132  }
133 
134  void print_seed(const Track &seed) {
135  std::cout << "MX - found seed with label=" << seed.label() << " nHits=" << seed.nFoundHits()
136  << " chi2=" << seed.chi2() << " posEta=" << seed.posEta() << " posPhi=" << seed.posPhi()
137  << " posR=" << seed.posR() << " posZ=" << seed.z() << " pT=" << seed.pT() << std::endl;
138  }
139 
140  void print_seed2(const TrackCand &seed) {
141  std::cout << "MX - found seed with nFoundHits=" << seed.nFoundHits() << " chi2=" << seed.chi2() << " x=" << seed.x()
142  << " y=" << seed.y() << " z=" << seed.z() << " px=" << seed.px() << " py=" << seed.py()
143  << " pz=" << seed.pz() << " pT=" << seed.pT() << std::endl;
144  }
145 
146  void print_seeds(const TrackVec &seeds) {
147  std::cout << "found total seeds=" << seeds.size() << std::endl;
148  for (auto &&seed : seeds) {
149  print_seed(seed);
150  }
151  }
152 
153  [[maybe_unused]] void print_seeds(const EventOfCombCandidates &event_of_comb_cands) {
154  for (int iseed = 0; iseed < event_of_comb_cands.size(); iseed++) {
155  print_seed2(event_of_comb_cands[iseed].front());
156  }
157  }
158 #endif
159 
160  bool sortCandByScore(const TrackCand &cand1, const TrackCand &cand2) {
161  return mkfit::sortByScoreTrackCand(cand1, cand2);
162  }
163 
164 #ifdef RNT_DUMP_MkF_SelHitIdcs
165  constexpr bool alwaysUseHitSelectionV2 = true;
166 #else
167  constexpr bool alwaysUseHitSelectionV2 = false;
168 #endif
169 } // end unnamed namespace
170 
171 //------------------------------------------------------------------------------
172 // Constructor and destructor
173 //------------------------------------------------------------------------------
174 
175 namespace mkfit {
176 
177  std::unique_ptr<MkBuilder> MkBuilder::make_builder(bool silent) { return std::make_unique<MkBuilder>(silent); }
178 
181 
182  std::pair<int, int> MkBuilder::max_hits_layer(const EventOfHits &eoh) const {
183  int maxN = 0;
184  int maxL = 0;
185  for (int l = 0; l < eoh.nLayers(); ++l) {
186  int lsize = eoh[l].nHits();
187  if (lsize > maxN) {
188  maxN = lsize;
189  maxL = eoh[l].layer_id();
190  }
191  }
192  return {maxN, maxL};
193  }
194 
196  int res = 0;
197  for (int i = 0; i < m_event_of_comb_cands.size(); ++i)
198  res += m_event_of_comb_cands[i].size();
199  return res;
200  }
201 
202  //------------------------------------------------------------------------------
203  // Common functions
204  //------------------------------------------------------------------------------
205 
206  void MkBuilder::begin_event(MkJob *job, Event *ev, const char *build_type) {
208 
209  m_job = job;
210  m_event = ev;
211 
215 
216  for (int i = 0; i < m_job->num_regions(); ++i) {
217  m_seedEtaSeparators[i] = 0;
218  m_seedMinLastLayer[i] = 9999;
219  m_seedMaxLastLayer[i] = 0;
220  }
221 
222  if (!m_silent) {
223  std::cout << "MkBuilder building tracks with '" << build_type << "'"
224  << ", iteration_index=" << job->m_iter_config.m_iteration_index
225  << ", track_algorithm=" << job->m_iter_config.m_track_algorithm << std::endl;
226  }
227  }
228 
230  m_job = nullptr;
231  m_event = nullptr;
232  }
233 
235  TrackVec tmp;
236  m_tracks.swap(tmp);
238  }
239 
240  void MkBuilder::import_seeds(const TrackVec &in_seeds,
241  const bool seeds_sorted,
242  std::function<insert_seed_foo> insert_seed) {
243  // bool debug = true;
244 
245  const int size = in_seeds.size();
246 
248  std::vector<unsigned> ranks;
249  if (!seeds_sorted) {
250  // We don't care about bins in phi, use low N to reduce overall number of bins.
252  axis<float, unsigned short, 8, 8> ax_eta(-3.0, 3.0, 64u);
254  part.m_phi_eta_foo = [&](float phi, float eta) { phi_eta_binnor.register_entry_safe(phi, eta); };
255 
256  phi_eta_binnor.begin_registration(size);
258  phi_eta_binnor.finalize_registration();
259  ranks.swap(phi_eta_binnor.m_ranks);
260  } else {
262  }
263 
264  for (int i = 0; i < size; ++i) {
265  int j = seeds_sorted ? i : ranks[i];
266  int reg = part.m_region[j];
267  ++m_seedEtaSeparators[reg];
268  }
269 
270  // Sum up region counts to contain actual ending indices and prepare insertion cursors.
271  // Fix min/max layers.
272  std::vector<int> seed_cursors(m_job->num_regions());
273  for (int reg = 1; reg < m_job->num_regions(); ++reg) {
274  seed_cursors[reg] = m_seedEtaSeparators[reg - 1];
275  m_seedEtaSeparators[reg] += m_seedEtaSeparators[reg - 1];
276  }
277 
278  // Actually imports seeds, detect last-hit layer range per region.
279  for (int i = 0; i < size; ++i) {
280  int j = seeds_sorted ? i : ranks[i];
281  int reg = part.m_region[j];
282  const Track &seed = in_seeds[j];
283  insert_seed(seed, j, reg, seed_cursors[reg]++);
284 
285  HitOnTrack hot = seed.getLastHitOnTrack();
288  }
289 
290  // Fix min/max layers
291  for (int reg = 0; reg < m_job->num_regions(); ++reg) {
292  if (m_seedMinLastLayer[reg] == 9999)
293  m_seedMinLastLayer[reg] = -1;
294  if (m_seedMaxLastLayer[reg] == 0)
295  m_seedMaxLastLayer[reg] = -1;
296  }
297 
298  // clang-format off
299  dprintf("MkBuilder::import_seeds finished import of %d seeds (last seeding layer min, max):\n"
300  " ec- = %d(%d,%d), t- = %d(%d,%d), brl = %d(%d,%d), t+ = %d(%d,%d), ec+ = %d(%d,%d).\n",
301  size,
307  // dcall(print_seeds(m_event_of_comb_cands));
308  // clang-format on
309  }
310 
311  //------------------------------------------------------------------------------
312 
315  int i = 0, place_pos = 0;
316 
317  dprintf("MkBuilder::filter_comb_cands Entering filter size eoccs.size=%d\n", eoccs.size());
318 
319  std::vector<int> removed_cnts(m_job->num_regions());
320  while (i < eoccs.size()) {
321  if (eoccs.cands_in_backward_rep())
322  eoccs[i].repackCandPostBkwSearch(0);
323  bool passed = filter(eoccs[i].front(), *m_job);
324 
325  if (!passed && attempt_all_cands) {
326  for (int j = 1; j < (int)eoccs[i].size(); ++j) {
327  if (eoccs.cands_in_backward_rep())
328  eoccs[i].repackCandPostBkwSearch(j);
329  if (filter(eoccs[i][j], *m_job)) {
330  eoccs[i][0] = eoccs[i][j]; // overwrite front, no need to std::swap() them
331  passed = true;
332  break;
333  }
334  }
335  }
336  if (passed) {
337  if (place_pos != i)
338  std::swap(eoccs[place_pos], eoccs[i]);
339  ++place_pos;
340  } else {
341  assert(eoccs[i].front().getEtaRegion() < m_job->num_regions());
342  ++removed_cnts[eoccs[i].front().getEtaRegion()];
343  }
344  ++i;
345  }
346 
347  int n_removed = 0;
348  for (int reg = 0; reg < m_job->num_regions(); ++reg) {
349  dprintf("MkBuilder::filter_comb_cands reg=%d: n_rem_was=%d removed_in_r=%d n_rem=%d, es_was=%d es_new=%d\n",
350  reg,
351  n_removed,
352  removed_cnts[reg],
353  n_removed + removed_cnts[reg],
354  m_seedEtaSeparators[reg],
355  m_seedEtaSeparators[reg] - n_removed - removed_cnts[reg]);
356 
357  n_removed += removed_cnts[reg];
358  m_seedEtaSeparators[reg] -= n_removed;
359  }
360 
361  eoccs.resizeAfterFiltering(n_removed);
362 
363  dprintf("MkBuilder::filter_comb_cands n_removed = %d, eoccs.size=%d\n", n_removed, eoccs.size());
364 
365  return n_removed;
366  }
367 
370  int min[5], max[5], gmin = 0, gmax = 0;
371  int i = 0;
372  for (int reg = 0; reg < 5; ++reg) {
373  min[reg] = 9999;
374  max[reg] = 0;
375  for (; i < m_seedEtaSeparators[reg]; i++) {
376  min[reg] = std::min(min[reg], eoccs[i].hotsSize());
377  max[reg] = std::max(max[reg], eoccs[i].hotsSize());
378  }
379  gmin = std::max(gmin, min[reg]);
380  gmax = std::max(gmax, max[reg]);
381  }
382  // clang-format off
383  printf("MkBuilder::find_min_max_hots_size MIN %3d -- [ %3d | %3d | %3d | %3d | %3d ] "
384  "MAX %3d -- [ %3d | %3d | %3d | %3d | %3d ]\n",
385  gmin, min[0], min[1], min[2], min[3], min[4],
386  gmax, max[0], max[1], max[2], max[3], max[4]);
387  // clang-format on
388  }
389 
390  void MkBuilder::select_best_comb_cands(bool clear_m_tracks, bool remove_missing_hits) {
391  if (clear_m_tracks)
392  m_tracks.clear();
393  export_best_comb_cands(m_tracks, remove_missing_hits);
394  }
395 
396  void MkBuilder::export_best_comb_cands(TrackVec &out_vec, bool remove_missing_hits) {
398  out_vec.reserve(out_vec.size() + eoccs.size());
399  for (int i = 0; i < eoccs.size(); i++) {
400  // Take the first candidate, if it exists.
401  if (!eoccs[i].empty()) {
402  const TrackCand &bcand = eoccs[i].front();
403  out_vec.emplace_back(bcand.exportTrack(remove_missing_hits));
404  }
405  }
406  }
407 
409  out_vec.reserve(out_vec.size() + m_tracks.size());
410  for (auto &t : m_tracks) {
411  out_vec.emplace_back(t);
412  }
413  }
414 
415  //------------------------------------------------------------------------------
416  // PrepareSeeds
417  //------------------------------------------------------------------------------
418 
421  int count = 0;
422 
423  for (int i = 0; i < (int)tv.size(); ++i) {
424  bool silly = tv[i].hasSillyValues(Const::nan_n_silly_print_bad_seeds,
426  "Post-cleaning seed silly value check and fix");
427  if (silly) {
428  ++count;
430  // XXXX MT
431  // Could do somethin smarter here: set as Stopped ? check in seed cleaning ?
432  tv.erase(tv.begin() + i);
433  --i;
434  }
435  }
436  }
437 
438  if (count > 0 && !m_silent) {
439  printf("Nan'n'Silly detected %d silly seeds (fix=%d, remove=%d).\n",
440  count,
443  }
444  }
445  }
446 
447  //------------------------------------------------------------------------------
448  // FindTracksBestHit
449  //------------------------------------------------------------------------------
450 
451  void MkBuilder::find_tracks_load_seeds_BH(const TrackVec &in_seeds, const bool seeds_sorted) {
452  // bool debug = true;
453  assert(!in_seeds.empty());
454  m_tracks.resize(in_seeds.size());
455 
456  import_seeds(in_seeds, seeds_sorted, [&](const Track &seed, int seed_idx, int region, int pos) {
457  m_tracks[pos] = seed;
458  m_tracks[pos].setNSeedHits(seed.nTotalHits());
459  m_tracks[pos].setEtaRegion(region);
460  });
461 
462  //dump seeds
463  dcall(print_seeds(m_tracks));
464  }
465 
467  // bool debug = true;
468 
470 
471  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
472  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
473  printf("No backward search plan for region %d\n", region);
474  return;
475  }
476 
477  // XXXXXX Select endcap / barrel only ...
478  // if (region != TrackerInfo::Reg_Endcap_Neg && region != TrackerInfo::Reg_Endcap_Pos)
479  // if (region != TrackerInfo::Reg_Barrel)
480  // return;
481 
482  const SteeringParams &st_par = m_job->steering_params(region);
483  const TrackerInfo &trk_info = m_job->m_trk_info;
484  const PropagationConfig &prop_config = trk_info.prop_config();
485 
486  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
487 
488  tbb::parallel_for(rosi.tbb_blk_rng_vec(), [&](const tbb::blocked_range<int> &blk_rng) {
489  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
490 
491  RangeOfSeedIndices rng = rosi.seed_rng(blk_rng);
492 
493  std::vector<int> trk_idcs(NN); // track indices in Matriplex
494  std::vector<int> trk_llay(NN); // last layer on input track
495 
496  while (rng.valid()) {
497  dprint(std::endl << "processing track=" << rng.m_beg << ", label=" << cands[rng.m_beg].label());
498 
499  int prev_layer = 9999;
500 
501  for (int i = rng.m_beg, ii = 0; i < rng.m_end; ++i, ++ii) {
502  int llay = cands[i].getLastHitLyr();
503  trk_llay[ii] = llay;
504  prev_layer = std::min(prev_layer, llay);
505 
506  dprintf(" %2d %2d %2d lay=%3d prev_layer=%d\n", ii, i, cands[i].label(), llay, prev_layer);
507  }
508  int curr_tridx = 0;
509 
510  auto layer_plan_it = st_par.make_iterator(iteration_dir);
511 
512  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
513  iteration_dir,
514  layer_plan_it.layer(),
515  layer_plan_it.last_layer());
516 
517  assert(layer_plan_it.is_pickup_only());
518 
519  int curr_layer = layer_plan_it.layer();
520 
521  mkfndr->m_Stopped.setVal(0);
522 
523  // Loop over layers, starting from after the seed.
524  // Consider inverting loop order and make layer outer, need to
525  // trade off hit prefetching with copy-out of candidates.
526  while (++layer_plan_it) {
527  prev_layer = curr_layer;
528  curr_layer = layer_plan_it.layer();
529  mkfndr->setup(prop_config,
532  m_job->m_iter_config.m_layer_configs[curr_layer],
533  st_par,
534  m_job->get_mask_for_layer(curr_layer),
535  m_event,
536  region,
537  m_job->m_in_fwd);
538 
539  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
540  const LayerInfo &layer_info = trk_info.layer(curr_layer);
541  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
542  dprint("at layer " << curr_layer << ", nHits in layer " << layer_of_hits.nHits());
543 
544  // Pick up seeds that become active on current layer -- unless already fully loaded.
545  if (curr_tridx < rng.n_proc()) {
546  int prev_tridx = curr_tridx;
547 
548  for (int i = rng.m_beg, ii = 0; i < rng.m_end; ++i, ++ii) {
549  if (trk_llay[ii] == prev_layer)
550  trk_idcs[curr_tridx++] = i;
551  }
552  if (curr_tridx > prev_tridx) {
553  dprintf("added %d seeds, started with %d\n", curr_tridx - prev_tridx, prev_tridx);
554 
555  mkfndr->inputTracksAndHitIdx(cands, trk_idcs, prev_tridx, curr_tridx, false, prev_tridx);
556  }
557  }
558 
559  if (layer_plan_it.is_pickup_only())
560  continue;
561 
562  dcall(pre_prop_print(curr_layer, mkfndr.get()));
563 
564  mkfndr->clearFailFlag();
565  (mkfndr.get()->*fnd_foos.m_propagate_foo)(
566  layer_info.propagate_to(), curr_tridx, prop_config.finding_inter_layer_pflags);
567 
568  dcall(post_prop_print(curr_layer, mkfndr.get()));
569 
570  mkfndr->selectHitIndices(layer_of_hits, curr_tridx);
571 
572  // Stop low-pT tracks that can not reach the current barrel layer.
573  if (layer_info.is_barrel()) {
574  const float r_min_sqr = layer_info.rin() * layer_info.rin();
575  for (int i = 0; i < curr_tridx; ++i) {
576  if (!mkfndr->m_Stopped[i]) {
577  if (mkfndr->radiusSqr(i, MkBase::iP) < r_min_sqr) {
579  mkfndr->m_Stopped[i] = 1;
580  mkfndr->outputTrackAndHitIdx(cands[rng.m_beg + i], i, false);
581  }
582  mkfndr->m_XWsrResult[i].m_wsr = WSR_Outside;
583  mkfndr->m_XHitSize[i] = 0;
584  }
585  } else { // make sure we don't add extra work for AddBestHit
586  mkfndr->m_XWsrResult[i].m_wsr = WSR_Outside;
587  mkfndr->m_XHitSize[i] = 0;
588  }
589  }
590  }
591 
592  // make candidates with best hit
593  dprint("make new candidates");
594 
595  mkfndr->addBestHit(layer_of_hits, curr_tridx, fnd_foos);
596 
597  // Stop tracks that have reached N_max_holes.
598  for (int i = 0; i < curr_tridx; ++i) {
599  if (!mkfndr->m_Stopped[i] && mkfndr->bestHitLastHoT(i).index == -2) {
600  mkfndr->m_Stopped[i] = 1;
601  mkfndr->outputTrackAndHitIdx(cands[rng.m_beg + i], i, false);
602  }
603  }
604 
605  } // end of layer loop
606 
607  mkfndr->outputNonStoppedTracksAndHitIdx(cands, trk_idcs, 0, curr_tridx, false);
608 
609  ++rng;
610  } // end of loop over candidates in a tbb chunk
611 
612  mkfndr->release();
613  }); // end parallel_for over candidates in a region
614  }); // end of parallel_for_each over regions
615  }
616 
617  //------------------------------------------------------------------------------
618  // FindTracksCombinatorial: Standard TBB and CloneEngine TBB
619  //------------------------------------------------------------------------------
620 
621  void MkBuilder::find_tracks_load_seeds(const TrackVec &in_seeds, const bool seeds_sorted) {
622  // This will sort seeds according to iteration configuration.
623  assert(!in_seeds.empty());
624  m_tracks.clear(); // m_tracks can be used for BkFit.
625 
626  m_event_of_comb_cands.reset((int)in_seeds.size(), m_job->max_max_cands());
627 
628  import_seeds(in_seeds, seeds_sorted, [&](const Track &seed, int seed_idx, int region, int pos) {
630  });
631  }
632 
633  int MkBuilder::find_tracks_unroll_candidates(std::vector<std::pair<int, int>> &seed_cand_vec,
634  int start_seed,
635  int end_seed,
636  int layer,
637  int prev_layer,
638  bool pickup_only,
639  SteeringParams::IterationType_e iteration_dir) {
640  int silly_count = 0;
641 
642  seed_cand_vec.clear();
643 
644  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
646 
647  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
649 
650  if (ccand.state() == CombCandidate::Dormant && ccand.pickupLayer() == prev_layer) {
652  }
653  if (!pickup_only && ccand.state() == CombCandidate::Finding) {
654  bool active = false;
655  for (int ic = 0; ic < (int)ccand.size(); ++ic) {
656  if (ccand[ic].getLastHitIdx() != -2) {
657  // Stop candidates with pT<X GeV
658  if (ccand[ic].pT() < iter_params.minPtCut) {
659  ccand[ic].addHitIdx(-2, layer, 0.0f);
660  continue;
661  }
662  // Check if the candidate is close to it's max_r, pi/2 - 0.2 rad (11.5 deg)
663  if (iteration_dir == SteeringParams::IT_FwdSearch && ccand[ic].pT() < 1.2) {
664  const float dphi = std::abs(ccand[ic].posPhi() - ccand[ic].momPhi());
665  if (ccand[ic].posRsq() > 625.f && dphi > 1.371f && dphi < 4.512f) {
666  // printf("Stopping cand at r=%f, posPhi=%.1f momPhi=%.2f pt=%.2f emomEta=%.2f\n",
667  // ccand[ic].posR(), ccand[ic].posPhi(), ccand[ic].momPhi(), ccand[ic].pT(), ccand[ic].momEta());
668  ccand[ic].addHitIdx(-2, layer, 0.0f);
669  continue;
670  }
671  }
672 
673  active = true;
674  seed_cand_vec.push_back(std::pair<int, int>(iseed, ic));
675  ccand[ic].resetOverlaps();
676 
678  if (ccand[ic].hasSillyValues(Const::nan_n_silly_print_bad_cands_every_layer,
680  "Per layer silly check"))
681  ++silly_count;
682  }
683  }
684  }
685  if (!active) {
687  }
688  }
689  }
690 
691  if constexpr (Const::nan_n_silly_check_cands_every_layer && silly_count > 0) {
692  m_nan_n_silly_per_layer_count += silly_count;
693  }
694 
695  return seed_cand_vec.size();
696  }
697 
699  const LayerInfo &layer_info,
700  std::vector<std::vector<TrackCand>> &tmp_cands,
701  const std::vector<std::pair<int, int>> &seed_cand_idx,
702  const int region,
703  const int start_seed,
704  const int itrack,
705  const int end) {
706  // XXXX-1 If I miss a layer, insert the original track into tmp_cands
707  // AND do not do it in FindCandidates as the position can be badly
708  // screwed by then. See comment there, too.
709  // One could also do a pre-check ... so as not to use up a slot.
710 
711  // bool debug = true;
712 
713  for (int ti = itrack; ti < end; ++ti) {
714  TrackCand &cand = m_event_of_comb_cands[seed_cand_idx[ti].first][seed_cand_idx[ti].second];
715  WSR_Result &w = mkfndr->m_XWsrResult[ti - itrack];
716 
717  // Low pT tracks can miss a barrel layer ... and should be stopped
718  dprintf("WSR Check label %d, seed %d, cand %d score %f -> wsr %d, in_gap %d\n",
719  cand.label(),
720  seed_cand_idx[ti].first,
721  seed_cand_idx[ti].second,
722  cand.score(),
723  w.m_wsr,
724  w.m_in_gap);
725 
726  if (w.m_wsr == WSR_Failed) {
727  // Fake outside so it does not get processed in FindTracks BH/Std/CE.
728  // [ Should add handling of WSR_Failed there, perhaps. ]
729  w.m_wsr = WSR_Outside;
730 
731  if (layer_info.is_barrel()) {
732  dprintf("Barrel cand propagation failed, got to r=%f ... layer is %f - %f\n",
733  mkfndr->radius(ti - itrack, MkBase::iP),
734  layer_info.rin(),
735  layer_info.rout());
736  // In barrel region, create a stopped replica. In transition region keep the original copy
737  // as there is still a chance to hit endcaps.
738  tmp_cands[seed_cand_idx[ti].first - start_seed].push_back(cand);
740  dprintf(" creating extra stopped held back candidate\n");
741  tmp_cands[seed_cand_idx[ti].first - start_seed].back().addHitIdx(-2, layer_info.layer_id(), 0);
742  }
743  }
744  // Never happens for endcap / propToZ
745  } else if (w.m_wsr == WSR_Outside) {
746  dprintf(" creating extra held back candidate\n");
747  tmp_cands[seed_cand_idx[ti].first - start_seed].push_back(cand);
748  } else if (w.m_wsr == WSR_Edge) {
749  // Do nothing special here, this case is handled also in MkFinder:findTracks()
750  }
751  }
752  }
753 
754  //------------------------------------------------------------------------------
755  // FindTracksCombinatorial: Standard TBB
756  //------------------------------------------------------------------------------
757 
759  // debug = true;
760 
762 
763  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
764  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
765  printf("No backward search plan for region %d\n", region);
766  return;
767  }
768 
769  const TrackerInfo &trk_info = m_job->m_trk_info;
770  const SteeringParams &st_par = m_job->steering_params(region);
771  const IterationParams &params = m_job->params();
772  const PropagationConfig &prop_config = trk_info.prop_config();
773 
774  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
775 
776  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
777  const int adaptiveSPT = std::clamp(
779  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
780 
781  // loop over seeds
782  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &seeds) {
783  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
784 
785  const int start_seed = seeds.begin();
786  const int end_seed = seeds.end();
787  const int n_seeds = end_seed - start_seed;
788 
789  std::vector<std::vector<TrackCand>> tmp_cands(n_seeds);
790  for (size_t iseed = 0; iseed < tmp_cands.size(); ++iseed) {
791  tmp_cands[iseed].reserve(2 * params.maxCandsPerSeed); //factor 2 seems reasonable to start with
792  }
793 
794  std::vector<std::pair<int, int>> seed_cand_idx;
795  seed_cand_idx.reserve(n_seeds * params.maxCandsPerSeed);
796 
797  auto layer_plan_it = st_par.make_iterator(iteration_dir);
798 
799  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
800  iteration_dir,
801  layer_plan_it.layer(),
802  layer_plan_it.last_layer());
803 
804  assert(layer_plan_it.is_pickup_only());
805 
806  int curr_layer = layer_plan_it.layer(), prev_layer;
807 
808  dprintf("\nMkBuilder::FindTracksStandard region=%d, seed_pickup_layer=%d, first_layer=%d\n",
809  region,
810  curr_layer,
811  layer_plan_it.next_layer());
812 
813  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
815 
816  // Loop over layers, starting from after the seed.
817  while (++layer_plan_it) {
818  prev_layer = curr_layer;
819  curr_layer = layer_plan_it.layer();
820  mkfndr->setup(prop_config,
822  iter_params,
823  m_job->m_iter_config.m_layer_configs[curr_layer],
824  st_par,
825  m_job->get_mask_for_layer(curr_layer),
826  m_event,
827  region,
828  m_job->m_in_fwd);
829 
830  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
831  const LayerInfo &layer_info = trk_info.layer(curr_layer);
832  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
833 
834  dprintf("\n* Processing layer %d\n", curr_layer);
835  mkfndr->begin_layer(layer_of_hits);
836 
837  int theEndCand = find_tracks_unroll_candidates(seed_cand_idx,
838  start_seed,
839  end_seed,
840  curr_layer,
841  prev_layer,
842  layer_plan_it.is_pickup_only(),
843  iteration_dir);
844 
845  dprintf(" Number of candidates to process: %d, nHits in layer: %d\n", theEndCand, layer_of_hits.nHits());
846 
847  if (layer_plan_it.is_pickup_only() || theEndCand == 0)
848  continue;
849 
850  // vectorized loop
851  for (int itrack = 0; itrack < theEndCand; itrack += NN) {
852  int end = std::min(itrack + NN, theEndCand);
853 
854  dprint("processing track=" << itrack << ", label="
855  << eoccs[seed_cand_idx[itrack].first][seed_cand_idx[itrack].second].label());
856 
857  //fixme find a way to deal only with the candidates needed in this thread
858  mkfndr->inputTracksAndHitIdx(eoccs.refCandidates(), seed_cand_idx, itrack, end, false);
859 
860  //propagate to layer
861  dcall(pre_prop_print(curr_layer, mkfndr.get()));
862 
863  mkfndr->clearFailFlag();
864  (mkfndr.get()->*fnd_foos.m_propagate_foo)(
865  layer_info.propagate_to(), end - itrack, prop_config.finding_inter_layer_pflags);
866 
867  dcall(post_prop_print(curr_layer, mkfndr.get()));
868 
869  dprint("now get hit range");
870 
871  if (alwaysUseHitSelectionV2 || iter_params.useHitSelectionV2)
872  mkfndr->selectHitIndicesV2(layer_of_hits, end - itrack);
873  else
874  mkfndr->selectHitIndices(layer_of_hits, end - itrack);
875 
877  mkfndr.get(), layer_info, tmp_cands, seed_cand_idx, region, start_seed, itrack, end);
878 
879  dprint("make new candidates");
880  mkfndr->findCandidates(layer_of_hits, tmp_cands, start_seed, end - itrack, fnd_foos);
881 
882  } //end of vectorized loop
883 
884  // sort the input candidates
885  for (int is = 0; is < n_seeds; ++is) {
886  dprint("dump seed n " << is << " with N_input_candidates=" << tmp_cands[is].size());
887 
888  std::sort(tmp_cands[is].begin(), tmp_cands[is].end(), sortCandByScore);
889  }
890 
891  // now fill out the output candidates
892  for (int is = 0; is < n_seeds; ++is) {
893  if (!tmp_cands[is].empty()) {
894  eoccs[start_seed + is].clear();
895 
896  // Put good candidates into eoccs, process -2 candidates.
897  int n_placed = 0;
898  bool first_short = true;
899  for (int ii = 0; ii < (int)tmp_cands[is].size() && n_placed < params.maxCandsPerSeed; ++ii) {
900  TrackCand &tc = tmp_cands[is][ii];
901 
902  // See if we have an overlap hit available, but only if we have a true hit in this layer
903  // and pT is above the pTCutOverlap
904  if (tc.pT() > params.pTCutOverlap && tc.getLastHitLyr() == curr_layer && tc.getLastHitIdx() >= 0) {
905  CombCandidate &ccand = eoccs[start_seed + is];
906 
907  HitMatch *hm = ccand[tc.originIndex()].findOverlap(
908  tc.getLastHitIdx(), layer_of_hits.refHit(tc.getLastHitIdx()).detIDinLayer());
909 
910  if (hm) {
911  tc.addHitIdx(hm->m_hit_idx, curr_layer, hm->m_chi2);
912  tc.incOverlapCount();
913  }
914  }
915 
916  if (tc.getLastHitIdx() != -2) {
917  eoccs[start_seed + is].emplace_back(tc);
918  ++n_placed;
919  } else if (first_short) {
920  first_short = false;
921  if (tc.score() > eoccs[start_seed + is].refBestShortCand().score()) {
922  eoccs[start_seed + is].setBestShortCand(tc);
923  }
924  }
925  }
926 
927  tmp_cands[is].clear();
928  }
929  }
930  mkfndr->end_layer();
931  } // end of layer loop
932  mkfndr->release();
933 
934  // final sorting
935  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
936  eoccs[iseed].mergeCandsAndBestShortOne(m_job->params(), st_par.m_track_scorer, true, true);
937  }
938  }); // end parallel-for over chunk of seeds within region
939  }); // end of parallel-for-each over eta regions
940 
941  // debug = false;
942  }
943 
944  //------------------------------------------------------------------------------
945  // FindTracksCombinatorial: CloneEngine TBB
946  //------------------------------------------------------------------------------
947 
949  // debug = true;
950 
952 
953  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
954  if (iteration_dir == SteeringParams::IT_BkwSearch && !m_job->steering_params(region).has_bksearch_plan()) {
955  printf("No backward search plan for region %d\n", region);
956  return;
957  }
958 
959  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
960 
961  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
962  const int adaptiveSPT = std::clamp(
964  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
965 
966  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &seeds) {
967  auto cloner = g_exe_ctx.m_cloners.makeOrGet();
968  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
969 
970  cloner->setup(m_job->params());
971 
972  // loop over layers
973  find_tracks_in_layers(*cloner, mkfndr.get(), iteration_dir, seeds.begin(), seeds.end(), region);
974 
975  mkfndr->release();
976  cloner->release();
977  });
978  });
979 
980  // debug = false;
981  }
982 
984  MkFinder *mkfndr,
985  SteeringParams::IterationType_e iteration_dir,
986  const int start_seed,
987  const int end_seed,
988  const int region) {
990  const TrackerInfo &trk_info = m_job->m_trk_info;
991  const SteeringParams &st_par = m_job->steering_params(region);
992  const IterationParams &params = m_job->params();
993  const PropagationConfig &prop_config = trk_info.prop_config();
994 
995  const int n_seeds = end_seed - start_seed;
996 
997  std::vector<std::pair<int, int>> seed_cand_idx;
998  std::vector<UpdateIndices> seed_cand_update_idx, seed_cand_overlap_idx;
999  seed_cand_idx.reserve(n_seeds * params.maxCandsPerSeed);
1000  seed_cand_update_idx.reserve(n_seeds * params.maxCandsPerSeed);
1001  seed_cand_overlap_idx.reserve(n_seeds * params.maxCandsPerSeed);
1002 
1003  std::vector<std::vector<TrackCand>> extra_cands(n_seeds);
1004  for (int ii = 0; ii < n_seeds; ++ii)
1005  extra_cands[ii].reserve(params.maxCandsPerSeed);
1006 
1007  cloner.begin_eta_bin(&eoccs, &seed_cand_update_idx, &seed_cand_overlap_idx, &extra_cands, start_seed, n_seeds);
1008 
1009  // Loop over layers, starting from after the seed.
1010 
1011  auto layer_plan_it = st_par.make_iterator(iteration_dir);
1012 
1013  dprintf("Made iterator for %d, first layer=%d ... end layer=%d\n",
1014  iteration_dir,
1015  layer_plan_it.layer(),
1016  layer_plan_it.last_layer());
1017 
1018  assert(layer_plan_it.is_pickup_only());
1019 
1020  int curr_layer = layer_plan_it.layer(), prev_layer;
1021 
1022  dprintf(
1023  "\nMkBuilder::find_tracks_in_layers region=%d, seed_pickup_layer=%d, first_layer=%d; start_seed=%d, "
1024  "end_seed=%d\n",
1025  region,
1026  curr_layer,
1027  layer_plan_it.next_layer(),
1028  start_seed,
1029  end_seed);
1030 
1031  auto &iter_params = (iteration_dir == SteeringParams::IT_BkwSearch) ? m_job->m_iter_config.m_backward_params
1033 
1034  // Loop over layers according to plan.
1035  while (++layer_plan_it) {
1036  prev_layer = curr_layer;
1037  curr_layer = layer_plan_it.layer();
1038  mkfndr->setup(prop_config,
1040  iter_params,
1041  m_job->m_iter_config.m_layer_configs[curr_layer],
1042  st_par,
1043  m_job->get_mask_for_layer(curr_layer),
1044  m_event,
1045  region,
1046  m_job->m_in_fwd);
1047 
1048  const bool pickup_only = layer_plan_it.is_pickup_only();
1049 
1050  const LayerInfo &layer_info = trk_info.layer(curr_layer);
1051  const LayerOfHits &layer_of_hits = m_job->m_event_of_hits[curr_layer];
1052  const FindingFoos &fnd_foos = FindingFoos::get_finding_foos(layer_info.is_barrel());
1053 
1054  dprintf("\n\n* Processing layer %d, %s\n\n", curr_layer, pickup_only ? "pickup only" : "full finding");
1055  mkfndr->begin_layer(layer_of_hits);
1056 
1057  const int theEndCand = find_tracks_unroll_candidates(
1058  seed_cand_idx, start_seed, end_seed, curr_layer, prev_layer, pickup_only, iteration_dir);
1059 
1060  dprintf(" Number of candidates to process: %d, nHits in layer: %d\n", theEndCand, layer_of_hits.nHits());
1061 
1062  // Don't bother messing with the clone engine if there are no candidates
1063  // (actually it crashes, so this protection is needed).
1064  // If there are no cands on this iteration, there won't be any later on either,
1065  // by the construction of the seed_cand_idx vector.
1066  // XXXXMT There might be cases in endcap where all tracks will miss the
1067  // next layer, but only relevant if we do geometric selection before.
1068 
1069  if (pickup_only || theEndCand == 0)
1070  continue;
1071 
1072  cloner.begin_layer(curr_layer);
1073 
1074  //vectorized loop
1075  for (int itrack = 0; itrack < theEndCand; itrack += NN) {
1076  const int end = std::min(itrack + NN, theEndCand);
1077 
1078 #ifdef DEBUG
1079  dprintf("\nProcessing track=%d, start_seed=%d, n_seeds=%d, theEndCand=%d, end=%d, nn=%d, end_eq_tec=%d\n",
1080  itrack,
1081  start_seed,
1082  n_seeds,
1083  theEndCand,
1084  end,
1085  end - itrack,
1086  end == theEndCand);
1087  dprintf(" (seed,cand): ");
1088  for (int i = itrack; i < end; ++i)
1089  dprintf("(%d,%d) ", seed_cand_idx[i].first, seed_cand_idx[i].second);
1090  dprintf("\n");
1091 #endif
1092 
1093  mkfndr->inputTracksAndHitIdx(eoccs.refCandidates(), seed_cand_idx, itrack, end, false);
1094 
1095 #ifdef DEBUG
1096  for (int i = itrack; i < end; ++i)
1097  dprintf(" track %d, idx %d is from seed %d\n", i, i - itrack, mkfndr->m_Label(i - itrack, 0, 0));
1098 #endif
1099 
1100  // propagate to current layer
1101  mkfndr->clearFailFlag();
1102  (mkfndr->*fnd_foos.m_propagate_foo)(
1103  layer_info.propagate_to(), end - itrack, prop_config.finding_inter_layer_pflags);
1104 
1105  dprint("now get hit range");
1106 
1107  if (alwaysUseHitSelectionV2 || iter_params.useHitSelectionV2)
1108  mkfndr->selectHitIndicesV2(layer_of_hits, end - itrack);
1109  else
1110  mkfndr->selectHitIndices(layer_of_hits, end - itrack);
1111 
1113  mkfndr, layer_info, extra_cands, seed_cand_idx, region, start_seed, itrack, end);
1114 
1115  // copy_out the propagated track params, errors only.
1116  // Do not, keep cands at last valid hit until actual update,
1117  // this requires change to propagation flags used in MkFinder::updateWithLastHit()
1118  // from intra-layer to inter-layer.
1119  // mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, true);
1120 
1121  // For prop-to-plane propagate from the last hit, not layer center.
1123  mkfndr->inputTracksAndHitIdx(eoccs.refCandidates(), seed_cand_idx, itrack, end, false);
1124  }
1125 
1126  dprint("make new candidates");
1127  cloner.begin_iteration();
1128 
1129  mkfndr->findCandidatesCloneEngine(layer_of_hits, cloner, start_seed, end - itrack, fnd_foos);
1130 
1131  cloner.end_iteration();
1132  } //end of vectorized loop
1133 
1134  cloner.end_layer();
1135 
1136  // Update loop of best candidates. CandCloner prepares the list of those
1137  // that need update (excluding all those with negative last hit index).
1138  // This is split into two sections - candidates without overlaps and with overlaps.
1139  // On CMS PU-50 the ratio of those is ~ 65 : 35 over all iterations.
1140  // Note, overlap recheck is only enabled for some iterations, e.g. pixelLess.
1141 
1142  const int theEndUpdater = seed_cand_update_idx.size();
1143 
1144  for (int itrack = 0; itrack < theEndUpdater; itrack += NN) {
1145  const int end = std::min(itrack + NN, theEndUpdater);
1146 
1147  mkfndr->inputTracksAndHits(eoccs.refCandidates(), layer_of_hits, seed_cand_update_idx, itrack, end, true);
1148 
1149  mkfndr->updateWithLoadedHit(end - itrack, layer_of_hits, fnd_foos);
1150 
1151  // copy_out the updated track params, errors only (hit-idcs and chi2 already set)
1152  mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, false);
1153  }
1154 
1155  const int theEndOverlapper = seed_cand_overlap_idx.size();
1156 
1157  for (int itrack = 0; itrack < theEndOverlapper; itrack += NN) {
1158  const int end = std::min(itrack + NN, theEndOverlapper);
1159 
1160  mkfndr->inputTracksAndHits(eoccs.refCandidates(), layer_of_hits, seed_cand_overlap_idx, itrack, end, true);
1161 
1162  mkfndr->updateWithLoadedHit(end - itrack, layer_of_hits, fnd_foos);
1163 
1164  mkfndr->copyOutParErr(eoccs.refCandidates_nc(), end - itrack, false);
1165 
1166  mkfndr->inputOverlapHits(layer_of_hits, seed_cand_overlap_idx, itrack, end);
1167 
1168  // XXXX Could also be calcChi2AndUpdate(), then copy-out would have to be done
1169  // below, choosing appropriate slot (with or without the overlap hit).
1170  // Probably in a dedicated MkFinder copyOutXyzz function.
1171  mkfndr->chi2OfLoadedHit(end - itrack, fnd_foos);
1172 
1173  for (int ii = itrack; ii < end; ++ii) {
1174  const int fi = ii - itrack;
1175  TrackCand &tc = eoccs[seed_cand_overlap_idx[ii].seed_idx][seed_cand_overlap_idx[ii].cand_idx];
1176 
1177  // XXXX For now we DO NOT use chi2 as this was how things were done before the post-update
1178  // chi2 check. To use it we should retune scoring function (might be even simpler).
1179  auto chi2Ovlp = mkfndr->m_Chi2[fi];
1180  if (mkfndr->m_FailFlag[fi] == 0 && chi2Ovlp >= 0.0f && chi2Ovlp <= 60.0f) {
1181  auto scoreCand =
1182  getScoreCand(st_par.m_track_scorer, tc, true /*penalizeTailMissHits*/, true /*inFindCandidates*/);
1183  tc.addHitIdx(seed_cand_overlap_idx[ii].ovlp_idx, curr_layer, chi2Ovlp);
1184  tc.incOverlapCount();
1185  auto scoreCandOvlp = getScoreCand(st_par.m_track_scorer, tc, true, true);
1186  if (scoreCand > scoreCandOvlp)
1187  tc.popOverlap();
1188  }
1189  }
1190  }
1191 
1192  // Check if cands are sorted, as expected.
1193 #ifdef DEBUG
1194  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
1195  auto &cc = eoccs[iseed];
1196 
1197  for (int i = 0; i < ((int)cc.size()) - 1; ++i) {
1198  if (cc[i].score() < cc[i + 1].score()) {
1199  printf("CloneEngine - NOT SORTED: layer=%d, iseed=%d (size=%lu)-- %d : %f smaller than %d : %f\n",
1200  curr_layer,
1201  iseed,
1202  cc.size(),
1203  i,
1204  cc[i].score(),
1205  i + 1,
1206  cc[i + 1].score());
1207  }
1208  }
1209  }
1210 #endif
1211  mkfndr->end_layer();
1212  } // end of layer loop
1213 
1214  cloner.end_eta_bin();
1215 
1216  // final sorting
1217  for (int iseed = start_seed; iseed < end_seed; ++iseed) {
1218  eoccs[iseed].mergeCandsAndBestShortOne(m_job->params(), st_par.m_track_scorer, true, true);
1219  }
1220  }
1221 
1222  //==============================================================================
1223  // BackwardFit
1224  //==============================================================================
1225 
1226 #ifdef DEBUG_FINAL_FIT
1227  namespace {
1228  // clang-format off
1229  void dprint_tcand(const TrackCand &t, int i) {
1230  dprintf(" %4d with q=%+d chi2=%7.3f pT=%7.3f eta=% 7.3f x=%.3f y=%.3f z=%.3f"
1231  " nHits=%2d label=%4d findable=%d\n",
1232  i, t.charge(), t.chi2(), t.pT(), t.momEta(), t.x(), t.y(), t.z(),
1233  t.nFoundHits(), t.label(), t.isFindable());
1234  }
1235  // clang-format on
1236  } // namespace
1237 #endif
1238 
1240  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
1241  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
1242 
1243  tbb::parallel_for(rosi.tbb_blk_rng_vec(), [&](const tbb::blocked_range<int> &blk_rng) {
1244  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
1245 
1246  RangeOfSeedIndices rng = rosi.seed_rng(blk_rng);
1247 
1248  while (rng.valid()) {
1249  // final backward fit
1250  fit_cands_BH(mkfndr.get(), rng.m_beg, rng.m_end, region);
1251 
1252  ++rng;
1253  }
1254  });
1255  });
1256  }
1257 
1258  void MkBuilder::fit_cands_BH(MkFinder *mkfndr, int start_cand, int end_cand, int region) {
1259  const SteeringParams &st_par = m_job->steering_params(region);
1260  const PropagationConfig &prop_config = m_job->m_trk_info.prop_config();
1261  mkfndr->setup_bkfit(prop_config, st_par, m_event);
1262 #ifdef DEBUG_FINAL_FIT
1264  bool debug = true;
1265 #endif
1266 
1267  for (int icand = start_cand; icand < end_cand; icand += NN) {
1268  const int end = std::min(icand + NN, end_cand);
1269 
1270 #ifdef DEBUG_FINAL_FIT
1271  dprintf("Pre Final fit for %d - %d\n", icand, end);
1272  for (int i = icand; i < end; ++i) {
1273  dprint_tcand(eoccs[i][0], i);
1274  }
1275 #endif
1276 
1277  bool chi_debug = false;
1278 #ifdef DEBUG_BACKWARD_FIT_BH
1279  redo_fit:
1280 #endif
1281 
1282  // input candidate tracks
1283  mkfndr->bkFitInputTracks(m_tracks, icand, end);
1284 
1285  // perform fit back to first layer on track
1286  mkfndr->bkFitFitTracksBH(m_job->m_event_of_hits, st_par, end - icand, chi_debug);
1287 
1288  // now move one last time to PCA
1289  if (prop_config.backward_fit_to_pca) {
1290  mkfndr->bkFitPropTracksToPCA(end - icand);
1291  }
1292 
1293 #ifdef DEBUG_BACKWARD_FIT_BH
1294  // Dump tracks with pT > 2 and chi2/dof > 20. Assumes MPT_SIZE=1.
1295  if (!chi_debug && 1.0f / mkfndr->m_Par[MkBase::iP].At(0, 3, 0) > 2.0f &&
1296  mkfndr->m_Chi2(0, 0, 0) / (eoccs[icand][0].nFoundHits() * 3 - 6) > 20.0f) {
1297  chi_debug = true;
1298 #ifdef MKFIT_STANDALONE
1299  printf("CHIHDR Event %d, Cand %3d, pT %f, chipdof %f ### NOTE x,y,z in cm, sigmas, deltas in mum ### !!!\n",
1300  m_event->evtID(),
1301 #else
1302  printf("CHIHDR Cand %3d, pT %f, chipdof %f ### NOTE x,y,z in cm, sigmas, deltas in mum ### !!!\n",
1303 #endif
1304  icand,
1305  1.0f / mkfndr->m_Par[MkBase::iP].At(0, 3, 0),
1306  mkfndr->m_Chi2(0, 0, 0) / (eoccs[icand][0].nFoundHits() * 3 - 6));
1307  // clang-format off
1308  printf("CHIHDR %3s %10s"
1309  " %10s %10s %10s %10s %11s %11s %11s"
1310  " %10s %10s %10s %10s %11s %11s %11s"
1311  " %10s %10s %10s %10s %10s %11s %11s\n",
1312  "lyr", "chi2",
1313  "x_h", "y_h", "z_h", "r_h", "sx_h", "sy_h", "sz_h",
1314  "x_t", "y_t", "z_t", "r_t", "sx_t", "sy_t", "sz_t",
1315  "pt", "phi", "theta", "phi_h", "phi_t", "d_xy", "d_z");
1316  // clang-format on
1317  goto redo_fit;
1318  }
1319 #endif
1320 
1321  // copy out full set of info at last propagated position
1322  mkfndr->bkFitOutputTracks(m_tracks, icand, end, prop_config.backward_fit_to_pca);
1323 
1324 #ifdef DEBUG_FINAL_FIT
1325  dprintf("Post Final fit for %d - %d\n", icand, end);
1326  for (int i = icand; i < end; ++i) {
1327  dprint_tcand(eoccs[i][0], i);
1328  }
1329 #endif
1330  }
1331  }
1332 
1333  //------------------------------------------------------------------------------
1334 
1337 
1338  tbb::parallel_for_each(m_job->regions_begin(), m_job->regions_end(), [&](int region) {
1339  const RegionOfSeedIndices rosi(m_seedEtaSeparators, region);
1340 
1341  // adaptive seeds per task based on the total estimated amount of work to divide among all threads
1342  const int adaptiveSPT = std::clamp(
1344  dprint("adaptiveSPT " << adaptiveSPT << " fill " << rosi.count() << "/" << eoccs.size() << " region " << region);
1345 
1346  tbb::parallel_for(rosi.tbb_blk_rng_std(adaptiveSPT), [&](const tbb::blocked_range<int> &cands) {
1347  auto mkfndr = g_exe_ctx.m_finders.makeOrGet();
1348 
1349  fit_cands(mkfndr.get(), cands.begin(), cands.end(), region);
1350  });
1351  });
1352  }
1353 
1354  void MkBuilder::fit_cands(MkFinder *mkfndr, int start_cand, int end_cand, int region) {
1356  const SteeringParams &st_par = m_job->steering_params(region);
1357  const PropagationConfig &prop_config = m_job->m_trk_info.prop_config();
1358  mkfndr->setup_bkfit(prop_config, st_par, m_event);
1359 
1360  int step = NN;
1361  for (int icand = start_cand; icand < end_cand; icand += step) {
1362  int end = std::min(icand + NN, end_cand);
1363 
1364  bool chi_debug = false;
1365 
1366 #ifdef DEBUG_FINAL_FIT
1367  bool debug = true;
1368  dprintf("Pre Final fit for %d - %d\n", icand, end);
1369  for (int i = icand; i < end; ++i) {
1370  dprint_tcand(eoccs[i][0], i);
1371  }
1372  chi_debug = true;
1373  static bool first = true;
1374  if (first) {
1375  // ./mkFit ... | perl -ne 'if (/^BKF_OVERLAP/) { s/^BKF_OVERLAP //og; print; }' > bkf_ovlp.rtt
1376  dprintf(
1377  "BKF_OVERLAP event/I:label/I:prod_type/I:is_findable/I:layer/I:is_stereo/I:is_barrel/I:"
1378  "pt/F:pt_cur/F:eta/F:phi/F:phi_cur/F:r_cur/F:z_cur/F:chi2/F:isnan/I:isfin/I:gtzero/I:hit_label/I:"
1379  "sx_t/F:sy_t/F:sz_t/F:d_xy/F:d_z/F\n");
1380  first = false;
1381  }
1382 #endif
1383 
1384  // input tracks
1385  mkfndr->bkFitInputTracks(eoccs, icand, end);
1386 
1387  // fit tracks back to first layer
1388  mkfndr->bkFitFitTracks(m_job->m_event_of_hits, st_par, end - icand, chi_debug);
1389 
1390  // now move one last time to PCA
1391  if (prop_config.backward_fit_to_pca) {
1392  mkfndr->bkFitPropTracksToPCA(end - icand);
1393  }
1394 
1395  mkfndr->bkFitOutputTracks(eoccs, icand, end, prop_config.backward_fit_to_pca);
1396 
1397 #ifdef DEBUG_FINAL_FIT
1398  dprintf("Post Final fit for %d - %d\n", icand, end);
1399  for (int i = icand; i < end; ++i) {
1400  dprint_tcand(eoccs[i][0], i);
1401  }
1402 #endif
1403  }
1404  mkfndr->release();
1405  }
1406 
1407 } // end namespace mkfit
void(MkBase::* m_propagate_foo)(float, const int, const PropagationFlags &)
Definition: FindingFoos.h:27
const IterationConfig & m_iter_config
Definition: MkJob.h:12
float getScoreCand(const track_score_func &score_func, const Track &cand1, bool penalizeTailMissHits=false, bool inFindCandidates=false)
Definition: Track.h:601
void import_seeds(const TrackVec &in_seeds, const bool seeds_sorted, std::function< insert_seed_foo > insert_seed)
Definition: MkBuilder.cc:240
void addHitIdx(int hitIdx, int hitLyr, float chi2)
int find_tracks_unroll_candidates(std::vector< std::pair< int, int >> &seed_cand_vec, int start_seed, int end_seed, int layer, int prev_layer, bool pickup_only, SteeringParams::IterationType_e iteration_dir)
Definition: MkBuilder.cc:633
IterationParams m_params
static void populate()
Definition: MkBuilder.cc:179
std::pair< int, int > max_hits_layer(const EventOfHits &eoh) const
Definition: MkBuilder.cc:182
#define CMS_SA_ALLOW
void export_tracks(TrackVec &out_vec)
Definition: MkBuilder.cc:408
IterationParams m_backward_params
void findTracksBestHit(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:466
void chi2OfLoadedHit(int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1882
Track exportTrack(bool remove_missing_hits=false) const
float radius(int itrack, int i) const
Definition: MkBase.h:24
static constexpr int iP
Definition: MkBase.h:19
void inputOverlapHits(const LayerOfHits &layer_of_hits, const std::vector< UpdateIndices > &idxs, int beg, int end)
Definition: MkFinder.cc:181
void resizeAfterFiltering(int n_removed)
float rin() const
Definition: TrackerInfo.h:68
void insertSeed(const Track &seed, int seed_idx, const track_score_func &score_func, int region, int pos)
void begin_eta_bin(EventOfCombCandidates *e_o_ccs, std::vector< UpdateIndices > *update_list, std::vector< UpdateIndices > *overlap_list, std::vector< std::vector< TrackCand >> *extra_cands, int start_seed, int n_seeds)
Definition: CandCloner.cc:25
float pT() const
Definition: Track.h:157
T w() const
void inputTracksAndHitIdx(const std::vector< Track > &tracks, int beg, int end, bool inputProp)
Definition: MkFinder.cc:99
void bkFitInputTracks(TrackVec &cands, int beg, int end)
Definition: MkFinder.cc:1929
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
constexpr bool nan_n_silly_print_bad_seeds
Definition: Config.h:19
std::atomic< int > m_nan_n_silly_per_layer_count
Definition: MkBuilder.h:138
void find_min_max_hots_size()
Definition: MkBuilder.cc:368
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
const auto regions_begin() const
Definition: MkJob.h:22
MPlexLV m_Par[2]
Definition: MkBase.h:102
MPlexQI m_FailFlag
Definition: MkBase.h:104
constexpr Process operator++(Process p)
Definition: DataFormats.h:68
void setState(SeedState_e ss)
void selectHitIndices(const LayerOfHits &layer_of_hits, const int N_proc, bool fill_binsearch_only=false)
Definition: MkFinder.cc:316
void setup(const PropagationConfig &pc, const IterationConfig &ic, const IterationParams &ip, const IterationLayerConfig &ilc, const SteeringParams &sp, const std::vector< bool > *ihm, const Event *ev, int region, bool infwd)
Definition: MkFinder.cc:30
void findTracksCloneEngine(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:948
int nLayers() const
void bkFitPropTracksToPCA(const int N_proc)
Definition: MkFinder.cc:2415
int evtID() const
Definition: Event.h:23
constexpr bool nan_n_silly_check_seeds
Definition: Config.h:18
void inputTracksAndHits(const std::vector< CombCandidate > &tracks, const LayerOfHits &layer_of_hits, const std::vector< UpdateIndices > &idxs, int beg, int end, bool inputProp)
Definition: MkFinder.cc:149
float propagate_to() const
Definition: TrackerInfo.h:74
void begin_event(MkJob *job, Event *ev, const char *build_type)
Definition: MkBuilder.cc:206
void release()
Definition: MkFinder.cc:56
assert(be >=bs)
const auto & params() const
Definition: MkJob.h:27
const EventOfHits & m_event_of_hits
Definition: MkJob.h:13
constexpr bool nan_n_silly_fixup_bad_cands_every_layer
Definition: Config.h:25
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
Definition: Electron.h:6
void finalize_registration()
Definition: binnor.h:289
track_score_func m_track_scorer
void backwardFitBH()
Definition: MkBuilder.cc:1239
unsigned int nHits() const
Definition: HitStructures.h:68
U second(std::pair< T, U > const &p)
#define dcall(x)
Definition: Debug.h:97
void end_iteration()
Definition: CandCloner.cc:66
char const * label
PropagationFlags finding_inter_layer_pflags
std::vector< C > m_ranks
Definition: binnor.h:211
void find_tracks_load_seeds_BH(const TrackVec &in_seeds, const bool seeds_sorted)
Definition: MkBuilder.cc:451
float score() const
Definition: Track.h:173
void findTracksStandard(SteeringParams::IterationType_e iteration_dir=SteeringParams::IT_FwdSearch)
Definition: MkBuilder.cc:758
std::function< filter_candidates_cf > filter_candidates_func
Definition: FunctionTypes.h:28
iterator make_iterator(IterationType_e type) const
std::vector< IterationLayerConfig > m_layer_configs
void reset(int new_capacity, int max_cands_per_seed, int expected_num_hots=128)
void find_tracks_load_seeds(const TrackVec &in_seeds, const bool seeds_sorted)
Definition: MkBuilder.cc:621
constexpr float PI
Definition: Config.h:7
void release_memory()
Definition: MkBuilder.cc:234
constexpr bool nan_n_silly_remove_bad_seeds
Definition: Config.h:21
TrackVec m_tracks
Definition: MkBuilder.h:128
void register_entry_safe(typename A1::real_t r1, typename A2::real_t r2)
Definition: binnor.h:282
constexpr Matriplex::idx_t NN
Definition: Matrix.h:43
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
void setup_bkfit(const PropagationConfig &pc, const SteeringParams &sp, const Event *ev)
Definition: MkFinder.cc:50
partition_seeds_func m_seed_partitioner
int layer_id() const
Definition: TrackerInfo.h:66
std::vector< int > m_seedEtaSeparators
Definition: MkBuilder.h:134
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void seed_post_cleaning(TrackVec &tv)
Definition: MkBuilder.cc:419
ExecutionContext g_exe_ctx
Definition: MkBuilder.cc:55
Pool< MkFinder > m_finders
Definition: MkBuilder.cc:40
double f[11][100]
Event * m_event
Definition: MkBuilder.h:125
float getHypot(float x, float y)
Definition: Hit.h:47
void clearFailFlag()
Definition: MkBase.h:96
void select_best_comb_cands(bool clear_m_tracks=false, bool remove_missing_hits=false)
Definition: MkBuilder.cc:390
constexpr int numThreadsFinder
Definition: Config.h:87
int filter_comb_cands(filter_candidates_func filter, bool attempt_all_cands)
Definition: MkBuilder.cc:313
Pool< CandCloner > m_cloners
Definition: MkBuilder.cc:38
int total_cands() const
Definition: MkBuilder.cc:195
void begin_registration(C n_items)
Definition: binnor.h:264
void begin_layer(const LayerOfHits &layer_of_hits)
Definition: MkFinder.cc:68
ii
Definition: cuy.py:589
trk_cand_vec_type::size_type size() const
const LayerInfo & layer(int l) const
Definition: TrackerInfo.h:206
const auto & steering_params(int i)
Definition: MkJob.h:25
const TrackerInfo & m_trk_info
Definition: MkJob.h:10
bool m_in_fwd
Definition: MkJob.h:18
void updateWithLoadedHit(int N_proc, const LayerOfHits &layer_of_hits, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1837
void selectHitIndicesV2(const LayerOfHits &layer_of_hits, const int N_proc)
Definition: MkFinder.cc:756
std::vector< Track > TrackVec
constexpr bool nan_n_silly_fixup_bad_seeds
Definition: Config.h:20
void begin_layer(int lay)
Definition: CandCloner.cc:48
Pool< MkFitter > m_fitters
Definition: MkBuilder.cc:39
#define debug
Definition: HDRShower.cc:19
const std::vector< CombCandidate > & refCandidates() const
int iseed
Definition: AMPTWrapper.h:134
bool sortByScoreTrackCand(const TrackCand &cand1, const TrackCand &cand2)
void bkFitFitTracks(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:2187
EventOfCombCandidates m_event_of_comb_cands
Definition: MkBuilder.h:131
std::vector< CombCandidate > & refCandidates_nc()
void find_tracks_handle_missed_layers(MkFinder *mkfndr, const LayerInfo &layer_info, std::vector< std::vector< TrackCand >> &tmp_cands, const std::vector< std::pair< int, int >> &seed_cand_idx, const int region, const int start_seed, const int itrack, const int end)
Definition: MkBuilder.cc:698
static const FindingFoos & get_finding_foos(bool is_barrel)
Definition: FindingFoos.cc:18
part
Definition: HCALResponse.h:20
std::vector< int > m_seedMaxLastLayer
Definition: MkBuilder.h:136
void populate(int n_thr)
Definition: MkBuilder.cc:42
float rout() const
Definition: TrackerInfo.h:69
constexpr bool nan_n_silly_check_cands_every_layer
Definition: Config.h:23
int getLastHitIdx() const
void begin_iteration()
Definition: CandCloner.cc:62
#define dprint(x)
Definition: Debug.h:95
MPlexQF m_Chi2
Definition: MkFinder.h:291
void export_best_comb_cands(TrackVec &out_vec, bool remove_missing_hits=false)
Definition: MkBuilder.cc:396
void bkFitOutputTracks(TrackVec &cands, int beg, int end, bool outputProp)
Definition: MkFinder.cc:1986
void bkFitFitTracksBH(const EventOfHits &eventofhits, const SteeringParams &st_par, const int N_proc, bool chiDebug=false)
Definition: MkFinder.cc:2034
static std::unique_ptr< MkBuilder > make_builder(bool silent=true)
Definition: MkBuilder.cc:177
constexpr int numSeedsPerTask
Definition: Config.h:89
constexpr int numThreadsEvents
Definition: Config.h:88
const auto regions_end() const
Definition: MkJob.h:23
int getLastHitLyr() const
void copyOutParErr(std::vector< CombCandidate > &seed_cand_vec, int N_proc, bool outputProp) const
Definition: MkFinder.cc:1906
void findCandidatesCloneEngine(const LayerOfHits &layer_of_hits, CandCloner &cloner, const int offset, const int N_proc, const FindingFoos &fnd_foos)
Definition: MkFinder.cc:1611
void fit_cands(MkFinder *mkfndr, int start_cand, int end_cand, int region)
Definition: MkBuilder.cc:1354
const std::vector< bool > * get_mask_for_layer(int layer)
Definition: MkJob.h:33
while(__syncthreads_or(more))
int max_max_cands() const
Definition: MkJob.h:31
constexpr bool usePropToPlane
Definition: Config.h:51
step
Definition: StallMonitor.cc:83
std::vector< int > m_seedMinLastLayer
Definition: MkBuilder.h:135
int originIndex() const
static void clear()
Definition: MkBuilder.cc:180
tmp
align.sh
Definition: createJobs.py:716
WSR_Result m_XWsrResult[NN]
Definition: MkFinder.h:321
constexpr bool nan_n_silly_print_bad_cands_every_layer
Definition: Config.h:24
void reset(double vett[256])
Definition: TPedValues.cc:11
int num_regions() const
Definition: MkJob.h:21
SeedState_e state() const
#define dprintf(...)
Definition: Debug.h:98
MPlexQI m_Label
Definition: MkFinder.h:292
void fit_cands_BH(MkFinder *mkfndr, int start_cand, int end_cand, int region)
Definition: MkBuilder.cc:1258
bool is_barrel() const
Definition: TrackerInfo.h:78
void find_tracks_in_layers(CandCloner &cloner, MkFinder *mkfndr, SteeringParams::IterationType_e iteration_dir, const int start_seed, const int end_seed, const int region)
Definition: MkBuilder.cc:983
void end_layer()
Definition: MkFinder.cc:88
const PropagationConfig & prop_config() const
Definition: TrackerInfo.h:219
const Hit & refHit(int i) const
float getPar(int itrack, int i, int par) const
Definition: MkBase.h:21