Skip to content

Commit

Permalink
Heterogeneous Cellular Automaton for pixel tracks
Browse files Browse the repository at this point in the history
Port the Cellular Automaton (back) to GPUs and CUDA, using the
`HeterogeneousEDProducer` approach:
  - do memory allocations in the framework begin stream
  - run the memory copies and kernels asynchronously, in a dedicated
    CUDA stream per framework stream

Use the new GPU::VecArray for holding repeated data structures.

By default, run on the GPU in all gpu-enable workflows (e.g. 10824.8).
  • Loading branch information
felicepantaleo authored and fwyzard committed Jun 16, 2018
1 parent 4f8add0 commit 96559f3
Show file tree
Hide file tree
Showing 12 changed files with 1,945 additions and 296 deletions.
12 changes: 10 additions & 2 deletions RecoPixelVertexing/PixelTriplets/plugins/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
<use name="RecoPixelVertexing/PixelTriplets"/>
<use name="RecoTracker/TkSeedingLayers"/>
<use name="RecoPixelVertexing/PixelTrackFitting"/>
<library file="*.cc" name="RecoPixelVertexingPixelTripletsPlugins">
<library file="*.cu *.cc" name="RecoPixelVertexingPixelTripletsPlugins">
<use name="cuda"/>
<flags EDM_PLUGIN="1"/>
<flags CUDA_FLAGS="--expt-relaxed-constexpr"/>
<use name="FWCore/Framework"/>
<use name="FWCore/PluginManager"/>
<use name="FWCore/ParameterSet"/>
<use name="HeterogeneousCore/Producer"/>
<use name="HeterogeneousCore/Product"/>
<use name="HeterogeneousCore/CUDACore"/>
<use name="cuda-api-wrappers"/>
</library>

<flags CXXFLAGS="-Ofast -fno-math-errno"/>
77 changes: 32 additions & 45 deletions RecoPixelVertexing/PixelTriplets/plugins/CAGraph.h
Original file line number Diff line number Diff line change
@@ -1,68 +1,55 @@
#ifndef RECOPIXELVERTEXING_PIXELTRIPLETS_CAGRAPH_H_
#define RECOPIXELVERTEXING_PIXELTRIPLETS_CAGRAPH_H_

#include <vector>
#include <array>
#include <string>
#include <vector>

struct CALayer
{
CALayer(const std::string& layerName, std::size_t numberOfHits )
: theName(layerName)
{
isOuterHitOfCell.resize(numberOfHits);
}

bool operator==(const std::string& otherString)
{
return otherString == theName;
}
struct CALayer {
CALayer(const std::string &layerName, std::size_t numberOfHits)
: theName(layerName) {
isOuterHitOfCell.resize(numberOfHits);
}

std::string name() const
{
return theName;
}
bool operator==(const std::string &otherString) {
return otherString == theName;
}

std::vector<int> theOuterLayerPairs;
std::vector<int> theInnerLayerPairs;
const std::string& name() const { return theName; }

std::vector<int> theOuterLayers;
std::vector<int> theInnerLayers;
std::vector< std::vector<unsigned int> > isOuterHitOfCell;
std::vector<int> theOuterLayerPairs;
std::vector<int> theInnerLayerPairs;

std::vector<int> theOuterLayers;
std::vector<int> theInnerLayers;
std::vector<std::vector<unsigned int>> isOuterHitOfCell;

private:

std::string theName;
std::string theName;
};

struct CALayerPair
{

CALayerPair(int a, int b)

{
theLayers[0] = a;
theLayers[1] = b;
}
struct CALayerPair {

CALayerPair(int a, int b)

{
theLayers[0] = a;
theLayers[1] = b;
}

bool operator==(const CALayerPair& otherLayerPair)
{
return (theLayers[0] == otherLayerPair.theLayers[0])
&& (theLayers[1] == otherLayerPair.theLayers[1]);
}
bool operator==(const CALayerPair &otherLayerPair) {
return (theLayers[0] == otherLayerPair.theLayers[0]) &&
(theLayers[1] == otherLayerPair.theLayers[1]);
}

std::array<int, 2> theLayers;
std::array<unsigned int, 2> theFoundCells= {{0,0}};
std::array<int, 2> theLayers;
std::array<unsigned int, 2> theFoundCells = {{0, 0}};
};

struct CAGraph
{
std::vector<CALayer> theLayers;
std::vector<CALayerPair> theLayerPairs;
std::vector<int> theRootLayers;
struct CAGraph {
std::vector<CALayer> theLayers;
std::vector<CALayerPair> theLayerPairs;
std::vector<int> theRootLayers;
};

#endif /* CAGRAPH_H_ */
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ void CAHitNtupletEDProducerT<T_Generator>::produce(edm::Event& iEvent, const edm
LogDebug("CAHitNtupletEDProducer") << "Creating ntuplets for " << regionDoublets.regionSize() << " regions, and " << regionDoublets.layerPairsSize() << " layer pairs";
std::vector<OrderedHitSeeds> ntuplets;
ntuplets.resize(regionDoublets.regionSize());
for(auto& ntuplet : ntuplets) ntuplet.reserve(localRA_.upper());
for(auto& ntuplet : ntuplets) ntuplet.reserve(localRA_.upper());

generator_.hitNtuplets(regionDoublets, ntuplets, iSetup, seedingLayerHits);
int index = 0;
for(const auto& regionLayerPairs: regionDoublets) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
#include "DataFormats/Common/interface/Handle.h"
#include "FWCore/Framework/interface/ConsumesCollector.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/PluginManager/interface/ModuleDef.h"
#include "FWCore/Utilities/interface/EDGetToken.h"
#include "FWCore/Utilities/interface/RunningAverage.h"
#include "HeterogeneousCore/CUDACore/interface/GPUCuda.h"
#include "HeterogeneousCore/CUDAServices/interface/CUDAService.h"
#include "HeterogeneousCore/Producer/interface/HeterogeneousEDProducer.h"

#include "CAHitQuadrupletGenerator.h"
#include "CAHitQuadrupletGeneratorGPU.h"
#include "RecoPixelVertexing/PixelTriplets/interface/OrderedHitSeeds.h"
#include "RecoTracker/TkHitPairs/interface/IntermediateHitDoublets.h"
#include "RecoTracker/TkHitPairs/interface/RegionsSeedingHitSets.h"

namespace {
void fillNtuplets(RegionsSeedingHitSets::RegionFiller &seedingHitSetsFiller,
const OrderedHitSeeds &quadruplets) {
for (const auto &quad : quadruplets) {
seedingHitSetsFiller.emplace_back(quad[0], quad[1], quad[2], quad[3]);
}
}
} // namespace

class CAHitNtupletHeterogeneousEDProducer
: public HeterogeneousEDProducer<heterogeneous::HeterogeneousDevices<
heterogeneous::GPUCuda, heterogeneous::CPU>> {
public:
CAHitNtupletHeterogeneousEDProducer(const edm::ParameterSet &iConfig);
~CAHitNtupletHeterogeneousEDProducer() = default;

static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
void beginStreamGPUCuda(edm::StreamID streamId,
cuda::stream_t<> &cudaStream) override;

void acquireGPUCuda(const edm::HeterogeneousEvent &iEvent,
const edm::EventSetup &iSetup,
cuda::stream_t<> &cudaStream) override;
void produceGPUCuda(edm::HeterogeneousEvent &iEvent,
const edm::EventSetup &iSetup,
cuda::stream_t<> &cudaStream) override;
void produceCPU(edm::HeterogeneousEvent &iEvent,
const edm::EventSetup &iSetup) override;

private:
edm::EDGetTokenT<IntermediateHitDoublets> doubletToken_;

edm::RunningAverage localRA_;
CAHitQuadrupletGeneratorGPU GPUGenerator_;
CAHitQuadrupletGenerator CPUGenerator_;

bool emptyRegionDoublets = false;
std::unique_ptr<RegionsSeedingHitSets> seedingHitSets_;
std::vector<OrderedHitSeeds> ntuplets_;
};

CAHitNtupletHeterogeneousEDProducer::CAHitNtupletHeterogeneousEDProducer(
const edm::ParameterSet &iConfig)
: HeterogeneousEDProducer(iConfig),
doubletToken_(consumes<IntermediateHitDoublets>(
iConfig.getParameter<edm::InputTag>("doublets"))),
GPUGenerator_(iConfig, consumesCollector()),
CPUGenerator_(iConfig, consumesCollector()) {
produces<RegionsSeedingHitSets>();
}

void CAHitNtupletHeterogeneousEDProducer::fillDescriptions(
edm::ConfigurationDescriptions &descriptions) {
edm::ParameterSetDescription desc;

desc.add<edm::InputTag>("doublets", edm::InputTag("hitPairEDProducer"));
CAHitQuadrupletGeneratorGPU::fillDescriptions(desc);
HeterogeneousEDProducer::fillPSetDescription(desc);
auto label = "caHitQuadrupletHeterogeneousEDProducer";
descriptions.add(label, desc);
}

void CAHitNtupletHeterogeneousEDProducer::beginStreamGPUCuda(
edm::StreamID streamId, cuda::stream_t<> &cudaStream) {
GPUGenerator_.allocateOnGPU();
}

void CAHitNtupletHeterogeneousEDProducer::acquireGPUCuda(
const edm::HeterogeneousEvent &iEvent, const edm::EventSetup &iSetup,
cuda::stream_t<> &cudaStream) {
edm::Handle<IntermediateHitDoublets> hdoublets;
iEvent.event().getByToken(doubletToken_, hdoublets);
const auto &regionDoublets = *hdoublets;

const SeedingLayerSetsHits &seedingLayerHits =
regionDoublets.seedingLayerHits();
if (seedingLayerHits.numberOfLayersInSet() <
CAHitQuadrupletGeneratorGPU::minLayers) {
throw cms::Exception("LogicError")
<< "CAHitNtupletHeterogeneousEDProducer expects "
"SeedingLayerSetsHits::numberOfLayersInSet() to be >= "
<< CAHitQuadrupletGeneratorGPU::minLayers << ", got "
<< seedingLayerHits.numberOfLayersInSet()
<< ". This is likely caused by a configuration error of this module, "
"HitPairEDProducer, or SeedingLayersEDProducer.";
}

seedingHitSets_ = std::make_unique<RegionsSeedingHitSets>();

if (regionDoublets.empty()) {
emptyRegionDoublets = true;
} else {
seedingHitSets_->reserve(regionDoublets.regionSize(), localRA_.upper());
GPUGenerator_.initEvent(iEvent.event(), iSetup);

LogDebug("CAHitNtupletHeterogeneousEDProducer")
<< "Creating ntuplets_ for " << regionDoublets.regionSize()
<< " regions, and " << regionDoublets.layerPairsSize()
<< " layer pairs";
ntuplets_.clear();
ntuplets_.resize(regionDoublets.regionSize());
for (auto &ntuplet : ntuplets_)
ntuplet.reserve(localRA_.upper());

GPUGenerator_.hitNtuplets(regionDoublets, ntuplets_, iSetup,
seedingLayerHits, cudaStream.id());
}
}

void CAHitNtupletHeterogeneousEDProducer::produceGPUCuda(
edm::HeterogeneousEvent &iEvent, const edm::EventSetup &iSetup,
cuda::stream_t<> &cudaStream) {

if (!emptyRegionDoublets) {
edm::Handle<IntermediateHitDoublets> hdoublets;
iEvent.getByToken(doubletToken_, hdoublets);
const auto &regionDoublets = *hdoublets;
const SeedingLayerSetsHits &seedingLayerHits =
regionDoublets.seedingLayerHits();
int index = 0;
for (const auto &regionLayerPairs : regionDoublets) {
const TrackingRegion &region = regionLayerPairs.region();
auto seedingHitSetsFiller = seedingHitSets_->beginRegion(&region);
GPUGenerator_.fillResults(regionDoublets, ntuplets_, iSetup,
seedingLayerHits, cudaStream.id());
fillNtuplets(seedingHitSetsFiller, ntuplets_[index]);
ntuplets_[index].clear();
index++;
}
localRA_.update(seedingHitSets_->size());
}
iEvent.put(std::move(seedingHitSets_));
}

void CAHitNtupletHeterogeneousEDProducer::produceCPU(
edm::HeterogeneousEvent &iEvent, const edm::EventSetup &iSetup) {
edm::Handle<IntermediateHitDoublets> hdoublets;
iEvent.getByToken(doubletToken_, hdoublets);
const auto &regionDoublets = *hdoublets;

const SeedingLayerSetsHits &seedingLayerHits =
regionDoublets.seedingLayerHits();
if (seedingLayerHits.numberOfLayersInSet() <
CAHitQuadrupletGenerator::minLayers) {
throw cms::Exception("LogicError")
<< "CAHitNtupletEDProducer expects "
"SeedingLayerSetsHits::numberOfLayersInSet() to be >= "
<< CAHitQuadrupletGenerator::minLayers << ", got "
<< seedingLayerHits.numberOfLayersInSet()
<< ". This is likely caused by a configuration error of this module, "
"HitPairEDProducer, or SeedingLayersEDProducer.";
}

auto seedingHitSets = std::make_unique<RegionsSeedingHitSets>();
if (regionDoublets.empty()) {
iEvent.put(std::move(seedingHitSets));
return;
}
seedingHitSets->reserve(regionDoublets.regionSize(), localRA_.upper());
CPUGenerator_.initEvent(iEvent.event(), iSetup);

LogDebug("CAHitNtupletEDProducer")
<< "Creating ntuplets_ for " << regionDoublets.regionSize()
<< " regions, and " << regionDoublets.layerPairsSize() << " layer pairs";
std::vector<OrderedHitSeeds> ntuplets_;
ntuplets_.resize(regionDoublets.regionSize());
for (auto &ntuplet : ntuplets_)
ntuplet.reserve(localRA_.upper());

CPUGenerator_.hitNtuplets(regionDoublets, ntuplets_, iSetup, seedingLayerHits);
int index = 0;
for (const auto &regionLayerPairs : regionDoublets) {
const TrackingRegion &region = regionLayerPairs.region();
auto seedingHitSetsFiller = seedingHitSets->beginRegion(&region);

fillNtuplets(seedingHitSetsFiller, ntuplets_[index]);
ntuplets_[index].clear();
index++;
}
localRA_.update(seedingHitSets->size());

iEvent.put(std::move(seedingHitSets));
}

DEFINE_FWK_MODULE(CAHitNtupletHeterogeneousEDProducer);
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class CAHitQuadrupletGenerator {
~CAHitQuadrupletGenerator() = default;

static void fillDescriptions(edm::ParameterSetDescription& desc);
static const char *fillDescriptionsLabel() { return "caHitQuadruplet"; }
static const char *fillDescriptionsLabel() { return "caHitQuadrupletDefault"; }

void initEvent(const edm::Event& ev, const edm::EventSetup& es);

Expand Down
Loading

0 comments on commit 96559f3

Please sign in to comment.