CMS 3D CMS Logo

PFClusterECLCC.h
Go to the documentation of this file.
1 #ifndef RecoParticleFlow_PFClusterProducer_plugins_alpaka_PFClusterECLCC_h
2 #define RecoParticleFlow_PFClusterProducer_plugins_alpaka_PFClusterECLCC_h
3 
8 
9 // The following comment block is required in using the ECL-CC algorithm for topological clustering
10 
11 /*
12  ECL-CC code: ECL-CC is a connected components graph algorithm. The CUDA
13  implementation thereof is quite fast. It operates on graphs stored in
14  binary CSR format.
15 
16  Copyright (c) 2017-2020, Texas State University. All rights reserved.
17 
18  Redistribution and use in source and binary forms, with or without
19  modification, are permitted provided that the following conditions are met:
20 
21  * Redistributions of source code must retain the above copyright
22  notice, this list of conditions and the following disclaimer.
23  * Redistributions in binary form must reproduce the above copyright
24  notice, this list of conditions and the following disclaimer in the
25  documentation and/or other materials provided with the distribution.
26  * Neither the name of Texas State University nor the names of its
27  contributors may be used to endorse or promote products derived from
28  this software without specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33  DISCLAIMED. IN NO EVENT SHALL TEXAS STATE UNIVERSITY BE LIABLE FOR ANY
34  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 
41  Authors: Jayadharini Jaiganesh and Martin Burtscher
42 
43  URL: The latest version of this code is available at
44  https://userweb.cs.txstate.edu/~burtscher/research/ECL-CC/.
45 
46  Publication: This work is described in detail in the following paper.
47  Jayadharini Jaiganesh and Martin Burtscher. A High-Performance Connected
48  Components Implementation for GPUs. Proceedings of the 2018 ACM International
49  Symposium on High-Performance Parallel and Distributed Computing, pp. 92-104.
50  June 2018.
51 */
52 
53 /*
54  The code is modified for the specific use-case of generating topological clusters
55  for PFClustering. It is adapted to work with the Alpaka portability library. The
56  kernels for processing vertices at warp and block level granularity have been
57  removed since the degree of vertices in our inputs is only ever 8; the number of
58  neighbors.
59 */
60 
62 
63  /* intermediate pointer jumping */
64 
65  ALPAKA_FN_ACC inline int representative(const int idx,
67  int curr = pfClusteringVars[idx].pfrh_topoId();
68  if (curr != idx) {
69  int next, prev = idx;
70  while (curr > (next = pfClusteringVars[curr].pfrh_topoId())) {
71  pfClusteringVars[prev].pfrh_topoId() = next;
72  prev = curr;
73  curr = next;
74  }
75  }
76  return curr;
77  }
78 
79  // Initial step of ECL-CC. Uses ID of first neighbour in edgeList with a smaller ID
80  class ECLCCInit {
81  public:
82  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
83  ALPAKA_FN_ACC void operator()(const TAcc& acc,
86  reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const {
87  const int nRH = pfRecHits.size();
88  for (int v : cms::alpakatools::elements_with_stride(acc, nRH)) {
89  const int beg = pfClusteringEdgeVars[v].pfrh_edgeIdx();
90  const int end = pfClusteringEdgeVars[v + 1].pfrh_edgeIdx();
91  int m = v;
92  int i = beg;
93  while ((m == v) && (i < end)) {
94  m = std::min(m, pfClusteringEdgeVars[i].pfrh_edgeList());
95  i++;
96  }
97  pfClusteringVars[v].pfrh_topoId() = m;
98  }
99  }
100  };
101 
102  // First edge processing kernel of ECL-CC
103  // Processes vertices
105  public:
106  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
107  ALPAKA_FN_ACC void operator()(const TAcc& acc,
110  reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const {
111  const int nRH = pfRecHits.size();
112 
113  for (int v : cms::alpakatools::elements_with_stride(acc, nRH)) {
114  const int vstat = pfClusteringVars[v].pfrh_topoId();
115  if (v != vstat) {
116  const int beg = pfClusteringEdgeVars[v].pfrh_edgeIdx();
117  const int end = pfClusteringEdgeVars[v + 1].pfrh_edgeIdx();
118  int vstat = representative(v, pfClusteringVars);
119  for (int i = beg; i < end; i++) {
120  const int nli = pfClusteringEdgeVars[i].pfrh_edgeList();
121  if (v > nli) {
122  int ostat = representative(nli, pfClusteringVars);
123  bool repeat;
124  do {
125  repeat = false;
126  if (vstat != ostat) {
127  int ret;
128  if (vstat < ostat) {
129  if ((ret = alpaka::atomicCas(acc, &pfClusteringVars[ostat].pfrh_topoId(), ostat, vstat)) != ostat) {
130  ostat = ret;
131  repeat = true;
132  }
133  } else {
134  if ((ret = alpaka::atomicCas(acc, &pfClusteringVars[vstat].pfrh_topoId(), vstat, ostat)) != vstat) {
135  vstat = ret;
136  repeat = true;
137  }
138  }
139  }
140  } while (repeat);
141  }
142  }
143  }
144  }
145  }
146  };
147 
148  /* link all vertices to sink */
149  class ECLCCFlatten {
150  public:
151  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
152  ALPAKA_FN_ACC void operator()(const TAcc& acc,
155  reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const {
156  const int nRH = pfRecHits.size();
157 
158  for (int v : cms::alpakatools::elements_with_stride(acc, nRH)) {
159  int next, vstat = pfClusteringVars[v].pfrh_topoId();
160  const int old = vstat;
161  while (vstat > (next = pfClusteringVars[vstat].pfrh_topoId())) {
162  vstat = next;
163  }
164  if (old != vstat)
165  pfClusteringVars[v].pfrh_topoId() = vstat;
166  }
167  }
168  };
169 
170  // ECL-CC ends
171 
172 } // namespace ALPAKA_ACCELERATOR_NAMESPACE
173 
174 #endif
ret
prodAgent to be discontinued
ALPAKA_FN_ACC int representative(const int idx, reco::PFClusteringVarsDeviceCollection::View pfClusteringVars)
ALPAKA_FN_ACC void operator()(const TAcc &acc, reco::PFRecHitHostCollection::ConstView pfRecHits, reco::PFClusteringVarsDeviceCollection::View pfClusteringVars, reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const
typename Layout::ConstView ConstView
ALPAKA_FN_ACC void operator()(const TAcc &acc, reco::PFRecHitHostCollection::ConstView pfRecHits, reco::PFClusteringVarsDeviceCollection::View pfClusteringVars, reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const
ALPAKA_FN_ACC void operator()(const TAcc &acc, reco::PFRecHitHostCollection::ConstView pfRecHits, reco::PFClusteringVarsDeviceCollection::View pfClusteringVars, reco::PFClusteringEdgeVarsDeviceCollection::View pfClusteringEdgeVars) const