Warning, /RecoTracker/PixelSeeding/plugins/CAHitNtupletGeneratorKernels.cu is written in an unsupported language. File is not indexed.
0001 #include <mutex>
0002
0003 #include "CAHitNtupletGeneratorKernelsImpl.h"
0004
0005 //#define GPU_DEBUG
0006 //#define NTUPLE_DEBUG
0007
0008 template <typename TrackerTraits>
0009 void CAHitNtupletGeneratorKernelsGPU<TrackerTraits>::launchKernels(const HitsConstView &hh,
0010 TkSoAView &tracks_view,
0011 cudaStream_t cudaStream) {
0012 using namespace gpuPixelDoublets;
0013 using namespace caHitNtupletGeneratorKernels;
0014
0015 // zero tuples
0016 cms::cuda::launchZero(&(tracks_view.hitIndices()), cudaStream); //TODO test .data()
0017
0018 int32_t nhits = hh.metadata().size();
0019
0020 #ifdef NTUPLE_DEBUG
0021 std::cout << "start tuple building. N hits " << nhits << std::endl;
0022 if (nhits < 2)
0023 std::cout << "too few hits " << nhits << std::endl;
0024 #endif
0025
0026 //
0027 // applying conbinatoric cleaning such as fishbone at this stage is too expensive
0028 //
0029
0030 auto nthTot = 64;
0031 auto stride = 4;
0032 auto blockSize = nthTot / stride;
0033 auto numberOfBlocks = this->nDoubletBlocks(blockSize);
0034 auto rescale = numberOfBlocks / 65536;
0035 blockSize *= (rescale + 1);
0036 numberOfBlocks = this->nDoubletBlocks(blockSize);
0037 assert(numberOfBlocks < 65536);
0038 assert(blockSize > 0 && 0 == blockSize % 16);
0039 dim3 blks(1, numberOfBlocks, 1);
0040 dim3 thrs(stride, blockSize, 1);
0041
0042 kernel_connect<TrackerTraits>
0043 <<<blks, thrs, 0, cudaStream>>>(this->device_hitTuple_apc_,
0044 this->device_hitToTuple_apc_, // needed only to be reset, ready for next kernel
0045 hh,
0046 this->device_theCells_.get(),
0047 this->device_nCells_,
0048 this->device_theCellNeighbors_.get(),
0049 this->isOuterHitOfCell_,
0050 this->params_.caParams_);
0051
0052 cudaCheck(cudaGetLastError());
0053
0054 // do not run the fishbone if there are hits only in BPIX1
0055 if (nhits > this->isOuterHitOfCell_.offset && this->params_.earlyFishbone_) {
0056 auto nthTot = 128;
0057 auto stride = 16;
0058 auto blockSize = nthTot / stride;
0059 auto numberOfBlocks = (nhits - this->isOuterHitOfCell_.offset + blockSize - 1) / blockSize;
0060 dim3 blks(1, numberOfBlocks, 1);
0061 dim3 thrs(stride, blockSize, 1);
0062 fishbone<TrackerTraits><<<blks, thrs, 0, cudaStream>>>(
0063 hh, this->device_theCells_.get(), this->device_nCells_, this->isOuterHitOfCell_, nhits, false);
0064 cudaCheck(cudaGetLastError());
0065 }
0066
0067 blockSize = 64;
0068 numberOfBlocks = (3 * this->params_.caParams_.maxNumberOfDoublets_ / 4 + blockSize - 1) / blockSize;
0069 kernel_find_ntuplets<TrackerTraits><<<numberOfBlocks, blockSize, 0, cudaStream>>>(hh,
0070 tracks_view,
0071 this->device_theCells_.get(),
0072 this->device_nCells_,
0073 this->device_theCellTracks_.get(),
0074 this->device_hitTuple_apc_,
0075 this->params_.caParams_);
0076 #ifdef GPU_DEBUG
0077 cudaDeviceSynchronize();
0078 cudaCheck(cudaGetLastError());
0079 #endif
0080 if (this->params_.doStats_)
0081 kernel_mark_used<TrackerTraits>
0082 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(this->device_theCells_.get(), this->device_nCells_);
0083 cudaCheck(cudaGetLastError());
0084
0085 #ifdef GPU_DEBUG
0086 cudaDeviceSynchronize();
0087 cudaCheck(cudaGetLastError());
0088 #endif
0089
0090 blockSize = 128;
0091 numberOfBlocks = (HitContainer::ctNOnes() + blockSize - 1) / blockSize;
0092
0093 cms::cuda::finalizeBulk<<<numberOfBlocks, blockSize, 0, cudaStream>>>(this->device_hitTuple_apc_,
0094 &tracks_view.hitIndices()); //TODO test .data()
0095
0096 #ifdef GPU_DEBUG
0097 cudaDeviceSynchronize();
0098 cudaCheck(cudaGetLastError());
0099 #endif
0100
0101 kernel_fillHitDetIndices<TrackerTraits><<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, hh);
0102 cudaCheck(cudaGetLastError());
0103
0104 #ifdef GPU_DEBUG
0105 cudaDeviceSynchronize();
0106 cudaCheck(cudaGetLastError());
0107 #endif
0108 kernel_fillNLayers<TrackerTraits>
0109 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->device_hitTuple_apc_);
0110 cudaCheck(cudaGetLastError());
0111
0112 #ifdef GPU_DEBUG
0113 cudaDeviceSynchronize();
0114 cudaCheck(cudaGetLastError());
0115 #endif
0116
0117 // remove duplicates (tracks that share a doublet)
0118 numberOfBlocks = this->nDoubletBlocks(blockSize);
0119
0120 kernel_earlyDuplicateRemover<TrackerTraits><<<numberOfBlocks, blockSize, 0, cudaStream>>>(
0121 this->device_theCells_.get(), this->device_nCells_, tracks_view, this->params_.dupPassThrough_);
0122 cudaCheck(cudaGetLastError());
0123 #ifdef GPU_DEBUG
0124 cudaDeviceSynchronize();
0125 cudaCheck(cudaGetLastError());
0126 #endif
0127
0128 blockSize = 128;
0129 numberOfBlocks = (3 * TrackerTraits::maxNumberOfTuples / 4 + blockSize - 1) / blockSize;
0130 kernel_countMultiplicity<TrackerTraits>
0131 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->device_tupleMultiplicity_.get());
0132 cms::cuda::launchFinalize(this->device_tupleMultiplicity_.get(), cudaStream);
0133 kernel_fillMultiplicity<TrackerTraits>
0134 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->device_tupleMultiplicity_.get());
0135 cudaCheck(cudaGetLastError());
0136 #ifdef GPU_DEBUG
0137 cudaDeviceSynchronize();
0138 cudaCheck(cudaGetLastError());
0139 #endif
0140
0141 // do not run the fishbone if there are hits only in BPIX1
0142 if (nhits > this->isOuterHitOfCell_.offset && this->params_.lateFishbone_) {
0143 auto nthTot = 128;
0144 auto stride = 16;
0145 auto blockSize = nthTot / stride;
0146 auto numberOfBlocks = (nhits - this->isOuterHitOfCell_.offset + blockSize - 1) / blockSize;
0147 dim3 blks(1, numberOfBlocks, 1);
0148 dim3 thrs(stride, blockSize, 1);
0149 fishbone<TrackerTraits><<<blks, thrs, 0, cudaStream>>>(
0150 hh, this->device_theCells_.get(), this->device_nCells_, this->isOuterHitOfCell_, nhits, true);
0151 cudaCheck(cudaGetLastError());
0152 }
0153
0154 #ifdef GPU_DEBUG
0155 cudaDeviceSynchronize();
0156 cudaCheck(cudaGetLastError());
0157 #endif
0158 }
0159
0160 template <typename TrackerTraits>
0161 void CAHitNtupletGeneratorKernelsGPU<TrackerTraits>::buildDoublets(const HitsConstView &hh,
0162 int32_t offsetBPIX2,
0163 cudaStream_t stream) {
0164 int32_t nhits = hh.metadata().size();
0165 using namespace gpuPixelDoublets;
0166
0167 using GPUCACell = GPUCACellT<TrackerTraits>;
0168 using OuterHitOfCell = typename GPUCACell::OuterHitOfCell;
0169 using CellNeighbors = typename GPUCACell::CellNeighbors;
0170 using CellTracks = typename GPUCACell::CellTracks;
0171 using OuterHitOfCellContainer = typename GPUCACell::OuterHitOfCellContainer;
0172
0173 this->isOuterHitOfCell_ = OuterHitOfCell{this->device_isOuterHitOfCell_.get(), offsetBPIX2};
0174
0175 #ifdef NTUPLE_DEBUG
0176 std::cout << "building Doublets out of " << nhits << " Hits" << std::endl;
0177 #endif
0178
0179 #ifdef GPU_DEBUG
0180 cudaDeviceSynchronize();
0181 cudaCheck(cudaGetLastError());
0182 #endif
0183
0184 // in principle we can use "nhits" to heuristically dimension the workspace...
0185 this->device_isOuterHitOfCell_ =
0186 cms::cuda::make_device_unique<OuterHitOfCellContainer[]>(std::max(1, nhits - offsetBPIX2), stream);
0187 assert(this->device_isOuterHitOfCell_.get());
0188
0189 this->isOuterHitOfCell_ = OuterHitOfCell{this->device_isOuterHitOfCell_.get(), offsetBPIX2};
0190
0191 this->cellStorage_ =
0192 cms::cuda::make_device_unique<unsigned char[]>(TrackerTraits::maxNumOfActiveDoublets * sizeof(CellNeighbors) +
0193 TrackerTraits::maxNumOfActiveDoublets * sizeof(CellTracks),
0194 stream);
0195 this->device_theCellNeighborsContainer_ = (CellNeighbors *)this->cellStorage_.get();
0196 this->device_theCellTracksContainer_ =
0197 (CellTracks *)(this->cellStorage_.get() + TrackerTraits::maxNumOfActiveDoublets * sizeof(CellNeighbors));
0198
0199 {
0200 int threadsPerBlock = 128;
0201 // at least one block!
0202 int blocks = (std::max(1, nhits - offsetBPIX2) + threadsPerBlock - 1) / threadsPerBlock;
0203 initDoublets<TrackerTraits><<<blocks, threadsPerBlock, 0, stream>>>(this->isOuterHitOfCell_,
0204 nhits,
0205 this->device_theCellNeighbors_.get(),
0206 this->device_theCellNeighborsContainer_,
0207 this->device_theCellTracks_.get(),
0208 this->device_theCellTracksContainer_);
0209 cudaCheck(cudaGetLastError());
0210 }
0211
0212 this->device_theCells_ =
0213 cms::cuda::make_device_unique<GPUCACell[]>(this->params_.caParams_.maxNumberOfDoublets_, stream);
0214
0215 #ifdef GPU_DEBUG
0216 cudaDeviceSynchronize();
0217 cudaCheck(cudaGetLastError());
0218 #endif
0219
0220 if (0 == nhits)
0221 return; // protect against empty events
0222
0223 // take all layer pairs into account
0224 auto nActualPairs = this->params_.nPairs();
0225
0226 int stride = 4;
0227 int threadsPerBlock = TrackerTraits::getDoubletsFromHistoMaxBlockSize / stride;
0228 int blocks = (4 * nhits + threadsPerBlock - 1) / threadsPerBlock;
0229 dim3 blks(1, blocks, 1);
0230 dim3 thrs(stride, threadsPerBlock, 1);
0231
0232 getDoubletsFromHisto<TrackerTraits><<<blks, thrs, 0, stream>>>(this->device_theCells_.get(),
0233 this->device_nCells_,
0234 this->device_theCellNeighbors_.get(),
0235 this->device_theCellTracks_.get(),
0236 hh,
0237 this->isOuterHitOfCell_,
0238 nActualPairs,
0239 this->params_.caParams_.maxNumberOfDoublets_,
0240 this->device_cellCuts_.get());
0241 cudaCheck(cudaGetLastError());
0242
0243 #ifdef GPU_DEBUG
0244 cudaDeviceSynchronize();
0245 cudaCheck(cudaGetLastError());
0246 #endif
0247 }
0248
0249 template <typename TrackerTraits>
0250 void CAHitNtupletGeneratorKernelsGPU<TrackerTraits>::classifyTuples(const HitsConstView &hh,
0251 TkSoAView &tracks_view,
0252 cudaStream_t cudaStream) {
0253 using namespace caHitNtupletGeneratorKernels;
0254
0255 int32_t nhits = hh.metadata().size();
0256
0257 auto blockSize = 64;
0258
0259 // classify tracks based on kinematics
0260 auto numberOfBlocks = this->nQuadrupletBlocks(blockSize);
0261 kernel_classifyTracks<TrackerTraits>
0262 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->params_.qualityCuts_);
0263
0264 if (this->params_.lateFishbone_) {
0265 // apply fishbone cleaning to good tracks
0266 numberOfBlocks = this->nDoubletBlocks(blockSize);
0267 kernel_fishboneCleaner<TrackerTraits>
0268 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(this->device_theCells_.get(), this->device_nCells_, tracks_view);
0269 cudaCheck(cudaGetLastError());
0270 }
0271
0272 // mark duplicates (tracks that share a doublet)
0273 numberOfBlocks = this->nDoubletBlocks(blockSize);
0274 kernel_fastDuplicateRemover<TrackerTraits><<<numberOfBlocks, blockSize, 0, cudaStream>>>(
0275 this->device_theCells_.get(), this->device_nCells_, tracks_view, this->params_.dupPassThrough_);
0276 cudaCheck(cudaGetLastError());
0277 #ifdef GPU_DEBUG
0278 cudaCheck(cudaDeviceSynchronize());
0279 #endif
0280
0281 if (this->params_.doSharedHitCut_ || this->params_.doStats_) {
0282 // fill hit->track "map"
0283 assert(this->hitToTupleView_.offSize > nhits);
0284 numberOfBlocks = this->nQuadrupletBlocks(blockSize);
0285 kernel_countHitInTracks<TrackerTraits>
0286 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->device_hitToTuple_.get()); //CHECK
0287 cudaCheck(cudaGetLastError());
0288 assert((this->hitToTupleView_.assoc == this->device_hitToTuple_.get()) &&
0289 (this->hitToTupleView_.offStorage == this->device_hitToTupleStorage_.get()) &&
0290 (this->hitToTupleView_.offSize > 0));
0291 cms::cuda::launchFinalize(this->hitToTupleView_, cudaStream);
0292 cudaCheck(cudaGetLastError());
0293 kernel_fillHitInTracks<TrackerTraits>
0294 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->device_hitToTuple_.get());
0295 cudaCheck(cudaGetLastError());
0296 #ifdef GPU_DEBUG
0297 cudaCheck(cudaDeviceSynchronize());
0298 #endif
0299 }
0300
0301 if (this->params_.doSharedHitCut_) {
0302 // mark duplicates (tracks that share at least one hit)
0303 numberOfBlocks = (this->hitToTupleView_.offSize + blockSize - 1) / blockSize;
0304
0305 kernel_rejectDuplicate<TrackerTraits><<<numberOfBlocks, blockSize, 0, cudaStream>>>(
0306 tracks_view, this->params_.minHitsForSharingCut_, this->params_.dupPassThrough_, this->device_hitToTuple_.get());
0307
0308 kernel_sharedHitCleaner<TrackerTraits>
0309 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(hh,
0310 tracks_view,
0311 this->params_.minHitsForSharingCut_,
0312 this->params_.dupPassThrough_,
0313 this->device_hitToTuple_.get());
0314
0315 if (this->params_.useSimpleTripletCleaner_) {
0316 kernel_simpleTripletCleaner<TrackerTraits>
0317 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view,
0318 this->params_.minHitsForSharingCut_,
0319 this->params_.dupPassThrough_,
0320 this->device_hitToTuple_.get());
0321 } else {
0322 kernel_tripletCleaner<TrackerTraits>
0323 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view,
0324 this->params_.minHitsForSharingCut_,
0325 this->params_.dupPassThrough_,
0326 this->device_hitToTuple_.get());
0327 }
0328 cudaCheck(cudaGetLastError());
0329 #ifdef GPU_DEBUG
0330 cudaCheck(cudaDeviceSynchronize());
0331 #endif
0332 }
0333
0334 if (this->params_.doStats_) {
0335 numberOfBlocks = (std::max(nhits, int(this->params_.caParams_.maxNumberOfDoublets_)) + blockSize - 1) / blockSize;
0336 kernel_checkOverflows<TrackerTraits>
0337 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view,
0338 this->device_tupleMultiplicity_.get(),
0339 this->device_hitToTuple_.get(),
0340 this->device_hitTuple_apc_,
0341 this->device_theCells_.get(),
0342 this->device_nCells_,
0343 this->device_theCellNeighbors_.get(),
0344 this->device_theCellTracks_.get(),
0345 this->isOuterHitOfCell_,
0346 nhits,
0347 this->params_.caParams_.maxNumberOfDoublets_,
0348 this->counters_);
0349 cudaCheck(cudaGetLastError());
0350 }
0351
0352 if (this->params_.doStats_) {
0353 // counters (add flag???)
0354 numberOfBlocks = (this->hitToTupleView_.offSize + blockSize - 1) / blockSize;
0355 kernel_doStatsForHitInTracks<TrackerTraits>
0356 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(this->device_hitToTuple_.get(), this->counters_);
0357 cudaCheck(cudaGetLastError());
0358 numberOfBlocks = (3 * TrackerTraits::maxNumberOfQuadruplets / 4 + blockSize - 1) / blockSize;
0359 kernel_doStatsForTracks<TrackerTraits>
0360 <<<numberOfBlocks, blockSize, 0, cudaStream>>>(tracks_view, this->counters_); //why sometimes yes and some no?
0361 cudaCheck(cudaGetLastError());
0362 }
0363 #ifdef GPU_DEBUG
0364 cudaDeviceSynchronize();
0365 cudaCheck(cudaGetLastError());
0366 #endif
0367
0368 #ifdef DUMP_GPU_TK_TUPLES
0369 static std::atomic<int> iev(0);
0370 static std::mutex lock;
0371 {
0372 std::lock_guard<std::mutex> guard(lock);
0373 ++iev;
0374 for (int k = 0; k < 20000; k += 500) {
0375 kernel_print_found_ntuplets<TrackerTraits>
0376 <<<1, 32, 0, cudaStream>>>(hh, tracks_view, this->device_hitToTuple_.get(), k, k + 500, iev);
0377 cudaCheck(cudaStreamSynchronize(cudaStream));
0378 }
0379 kernel_print_found_ntuplets<TrackerTraits>
0380 <<<1, 32, 0, cudaStream>>>(hh, tracks_view, this->device_hitToTuple_.get(), 20000, 1000000, iev);
0381 cudaCheck(cudaStreamSynchronize(cudaStream));
0382 }
0383 #endif
0384 }
0385
0386 template <typename TrackerTraits>
0387 void CAHitNtupletGeneratorKernelsGPU<TrackerTraits>::printCounters(Counters const *counters) {
0388 caHitNtupletGeneratorKernels::kernel_printCounters<<<1, 1>>>(counters);
0389 }
0390
0391 template class CAHitNtupletGeneratorKernelsGPU<pixelTopology::Phase1>;
0392 template class CAHitNtupletGeneratorKernelsGPU<pixelTopology::Phase2>;
0393 template class CAHitNtupletGeneratorKernelsGPU<pixelTopology::HIonPhase1>;