Skip to content

Commit

Permalink
Make GPU-CPU cluster matching deterministic (#294)
Browse files Browse the repository at this point in the history
Makes the GPU-CPU cluster matching deterministic by intrusively marking CPU clusters with the cluster index.
Reuse existing padding space to store the extra transient field, so that the size of SiPixelCluster does not increase.
There is still a warning in case of mismatch of the content of the cluster (based on charge comparison), that can eventually be downgraded to a debug message.

Properly rewrite the loop in the RawToDigi_kernel .

Remove obsolete code (comments and configuration parameters) in SiPixelRawToClusterCUDA and SiPixelRawToClusterGPUKernel.
  • Loading branch information
cmsbuild authored and fwyzard committed Dec 25, 2020
1 parent 3cec268 commit 8b4a4ab
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 168 deletions.
229 changes: 124 additions & 105 deletions DataFormats/SiPixelCluster/interface/SiPixelCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! Class to contain and store all the topological information of pixel clusters:
//! charge, global size, size and the barycenter in x and y
//! local directions. It builds a vector of SiPixel (which is
//! an inner class) and a container of channels.
//! an inner class) and a container of channels.
//!
//! March 2007: Edge methods moved to RectangularPixelTopology class (V.Chiochia)
//! Feb 2008: Modify the Pixel class from float to shorts
Expand All @@ -21,158 +21,166 @@
#include <vector>
#include <cstdint>
#include <cassert>
#include <limits>

class PixelDigi;

class SiPixelCluster {
public:

class Pixel {
public:
constexpr Pixel() : x(0), y(0), adc(0) {} // for root
constexpr Pixel(int pix_x, int pix_y, int pix_adc) : x(pix_x), y(pix_y), adc(pix_adc) {}
uint16_t x;
constexpr Pixel() : x(0), y(0), adc(0){} // for root
constexpr Pixel(int pix_x, int pix_y, int pix_adc) :
x(pix_x), y(pix_y), adc(pix_adc) {}
uint16_t x;
uint16_t y;
uint16_t adc;
};

//--- Integer shift in x and y directions.
class Shift {
public:
constexpr Shift(int dx, int dy) : dx_(dx), dy_(dy) {}
constexpr Shift( int dx, int dy) : dx_(dx), dy_(dy) {}
constexpr Shift() : dx_(0), dy_(0) {}
constexpr int dx() const { return dx_; }
constexpr int dy() const { return dy_; }

constexpr int dx() const { return dx_;}
constexpr int dy() const { return dy_;}
private:
int dx_;
int dy_;
};

//--- Position of a SiPixel
class PixelPos {
public:
constexpr PixelPos() : row_(0), col_(0) {}
constexpr PixelPos(int row, int col) : row_(row), col_(col) {}
constexpr int row() const { return row_; }
constexpr int col() const { return col_; }
constexpr PixelPos operator+(const Shift& shift) const { return PixelPos(row() + shift.dx(), col() + shift.dy()); }

constexpr PixelPos(int row, int col) : row_(row) , col_(col) {}
constexpr int row() const { return row_;}
constexpr int col() const { return col_;}
constexpr PixelPos operator+( const Shift& shift) const {
return PixelPos( row() + shift.dx(), col() + shift.dy());
}
private:
int row_;
int col_;
};

typedef std::vector<PixelDigi>::const_iterator PixelDigiIter;
typedef std::pair<PixelDigiIter, PixelDigiIter> PixelDigiRange;

static constexpr unsigned int MAXSPAN = 255;
static constexpr unsigned int MAXPOS = 2047;


typedef std::vector<PixelDigi>::const_iterator PixelDigiIter;
typedef std::pair<PixelDigiIter,PixelDigiIter> PixelDigiRange;


static constexpr unsigned int MAXSPAN=255;
static constexpr unsigned int MAXPOS=2047;

/** Construct from a range of digis that form a cluster and from
* a DetID. The range is assumed to be non-empty.
*/

SiPixelCluster() {}

SiPixelCluster(unsigned int isize,
uint16_t const* adcs,
uint16_t const* xpos,
uint16_t const* ypos,
uint16_t const xmin,
uint16_t const ymin)
: thePixelOffset(2 * isize), thePixelADC(adcs, adcs + isize) {

SiPixelCluster(unsigned int isize, uint16_t const * adcs,
uint16_t const * xpos, uint16_t const * ypos,
uint16_t const xmin, uint16_t const ymin) :
thePixelOffset(2*isize), thePixelADC(adcs,adcs+isize) {
uint16_t maxCol = 0;
uint16_t maxRow = 0;
for (unsigned int i = 0; i != isize; ++i) {
uint16_t xoffset = xpos[i] - xmin;
uint16_t yoffset = ypos[i] - ymin;
thePixelOffset[i * 2] = std::min(uint16_t(MAXSPAN), xoffset);
thePixelOffset[i * 2 + 1] = std::min(uint16_t(MAXSPAN), yoffset);
if (xoffset > maxRow)
maxRow = xoffset;
if (yoffset > maxCol)
maxCol = yoffset;
for (unsigned int i=0; i!=isize; ++i) {
uint16_t xoffset = xpos[i]-xmin;
uint16_t yoffset = ypos[i]-ymin;
thePixelOffset[i*2] = std::min(uint16_t(MAXSPAN),xoffset);
thePixelOffset[i*2+1] = std::min(uint16_t(MAXSPAN),yoffset);
if (xoffset > maxRow) maxRow = xoffset;
if (yoffset > maxCol) maxCol = yoffset;
}
packRow(xmin, maxRow);
packCol(ymin, maxCol);
packRow(xmin,maxRow);
packCol(ymin,maxCol);
}



// obsolete (only for regression tests)
SiPixelCluster(const PixelPos& pix, int adc);
void add(const PixelPos& pix, int adc);

// Analog linear average position (barycenter)
SiPixelCluster( const PixelPos& pix, int adc);
void add( const PixelPos& pix, int adc);
// Analog linear average position (barycenter)
float x() const {
float qm = 0.0;
int isize = thePixelADC.size();
for (int i = 0; i < isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i * 2] + minPixelRow() + 0.5f);
return qm / charge();
for (int i=0; i<isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i*2] + minPixelRow() + 0.5f);
return qm/charge();
}

float y() const {
float qm = 0.0;
int isize = thePixelADC.size();
for (int i = 0; i < isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i * 2 + 1] + minPixelCol() + 0.5f);
return qm / charge();
for (int i=0; i<isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i*2+1] + minPixelCol() + 0.5f);
return qm/charge();
}

// Return number of pixels.
int size() const { return thePixelADC.size(); }

int size() const { return thePixelADC.size();}
// Return cluster dimension in the x direction.
int sizeX() const { return rowSpan() + 1; }

int sizeX() const { return rowSpan() +1;}
// Return cluster dimension in the y direction.
int sizeY() const { return colSpan() + 1; }

int sizeY() const { return colSpan() +1;}


inline int charge() const {
int qm = 0;
int isize = thePixelADC.size();
for (int i = 0; i < isize; ++i)
for (int i=0; i<isize; ++i)
qm += thePixelADC[i];
return qm;
} // Return total cluster charge.

inline int minPixelRow() const { return theMinPixelRow; } // The min x index.
inline int maxPixelRow() const { return minPixelRow() + rowSpan(); } // The max x index.
inline int minPixelCol() const { return theMinPixelCol; } // The min y index.
inline int maxPixelCol() const { return minPixelCol() + colSpan(); } // The max y index.

const std::vector<uint8_t>& pixelOffset() const { return thePixelOffset; }
const std::vector<uint16_t>& pixelADC() const { return thePixelADC; }

} // Return total cluster charge.

inline int minPixelRow() const { return theMinPixelRow;} // The min x index.
inline int maxPixelRow() const { return minPixelRow() + rowSpan();} // The max x index.
inline int minPixelCol() const { return theMinPixelCol;} // The min y index.
inline int maxPixelCol() const { return minPixelCol() + colSpan();} // The max y index.


const std::vector<uint8_t> & pixelOffset() const { return thePixelOffset;}
const std::vector<uint16_t> & pixelADC() const { return thePixelADC;}

// obsolete, use single pixel access below
const std::vector<Pixel> pixels() const {
std::vector<Pixel> oldPixVector;
int isize = thePixelADC.size();
oldPixVector.reserve(isize);
for (int i = 0; i < isize; ++i) {
oldPixVector.reserve(isize);
for(int i=0; i<isize; ++i) {
oldPixVector.push_back(pixel(i));
}
return oldPixVector;
}

// infinite faster than above...
Pixel pixel(int i) const {
return Pixel(minPixelRow() + thePixelOffset[i * 2], minPixelCol() + thePixelOffset[i * 2 + 1], thePixelADC[i]);
return Pixel(minPixelRow() + thePixelOffset[i*2],
minPixelCol() + thePixelOffset[i*2+1],
thePixelADC[i]
);
}

private:
static int overflow_(uint16_t span) { return span == uint16_t(MAXSPAN); }

static int overflow_(uint16_t span) { return span==uint16_t(MAXSPAN);}

public:
int colSpan() const { return thePixelColSpan; }


int colSpan() const {return thePixelColSpan; }

int rowSpan() const { return thePixelRowSpan; }



bool overflowCol() const { return overflow_(thePixelColSpan); }

bool overflowRow() const { return overflow_(thePixelRowSpan); }

bool overflow() const { return overflowCol() || overflowRow(); }

bool overflow() const { return overflowCol() || overflowRow(); }
void packCol(uint16_t ymin, uint16_t yspan) {
theMinPixelCol = ymin;
thePixelColSpan = std::min(yspan, uint16_t(MAXSPAN));
Expand All @@ -181,40 +189,51 @@ class SiPixelCluster {
theMinPixelRow = xmin;
thePixelRowSpan = std::min(xspan, uint16_t(MAXSPAN));
}

// [email protected], 01/05/12
// [email protected], 01/05/12
// Getters and setters for the newly added data members (err_x and err_y). See below.
void setSplitClusterErrorX(float errx) { err_x = errx; }
void setSplitClusterErrorY(float erry) { err_y = erry; }
float getSplitClusterErrorX() const { return err_x; }
float getSplitClusterErrorY() const { return err_y; }
void setSplitClusterErrorX( float errx ) { err_x = errx; }
void setSplitClusterErrorY( float erry ) { err_y = erry; }
float getSplitClusterErrorX() const { return err_x; }
float getSplitClusterErrorY() const { return err_y; }

// the original id (they get sorted)
auto originalId() const { return theOriginalClusterId;}
void setOriginalId(uint16_t id) { theOriginalClusterId=id;}

private:
std::vector<uint8_t> thePixelOffset;

std::vector<uint8_t> thePixelOffset;
std::vector<uint16_t> thePixelADC;

uint16_t theMinPixelRow = MAXPOS; // Minimum pixel index in the x direction (low edge).
uint16_t theMinPixelCol = MAXPOS; // Minimum pixel index in the y direction (left edge).
uint8_t thePixelRowSpan = 0; // Span pixel index in the x direction (low edge).
uint8_t thePixelColSpan = 0; // Span pixel index in the y direction (left edge).

float err_x = -99999.9f;
float err_y = -99999.9f;


uint16_t theMinPixelRow=MAXPOS; // Minimum pixel index in the x direction (low edge).
uint16_t theMinPixelCol=MAXPOS; // Minimum pixel index in the y direction (left edge).
uint8_t thePixelRowSpan=0; // Span pixel index in the x direction (low edge).
uint8_t thePixelColSpan=0; // Span pixel index in the y direction (left edge).

uint16_t theOriginalClusterId=std::numeric_limits<uint16_t>::max();

float err_x=-99999.9f;
float err_y=-99999.9f;

};


// Comparison operators (needed by DetSetVector)
inline bool operator<(const SiPixelCluster& one, const SiPixelCluster& other) {
if (one.minPixelRow() < other.minPixelRow()) {
inline bool operator<( const SiPixelCluster& one, const SiPixelCluster& other) {
if ( one.minPixelRow() < other.minPixelRow() ) {
return true;
} else if (one.minPixelRow() > other.minPixelRow()) {
} else if ( one.minPixelRow() > other.minPixelRow() ) {
return false;
} else if (one.minPixelCol() < other.minPixelCol()) {
} else if ( one.minPixelCol() < other.minPixelCol() ) {
return true;
} else {
return false;
}
}


#include "DataFormats/Common/interface/DetSetVector.h"
#include "DataFormats/Common/interface/DetSetVectorNew.h"
#include "DataFormats/Common/interface/Ref.h"
Expand All @@ -227,4 +246,4 @@ typedef edm::RefProd<SiPixelClusterCollection> SiPixelClusterRefProd;

typedef edmNew::DetSetVector<SiPixelCluster> SiPixelClusterCollectionNew;
typedef edm::Ref<SiPixelClusterCollectionNew, SiPixelCluster> SiPixelClusterRefNew;
#endif
#endif
1 change: 1 addition & 0 deletions DataFormats/SiPixelCluster/src/classes_def.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<version ClassVersion="11" checksum="1473312403"/>
<version ClassVersion="12" checksum="2042538185"/>
<version ClassVersion="13" checksum="2314992115"/>
<field name="theOriginalClusterId" transient="true"/>
<field name="err_x" transient="true"/>
<field name="err_y" transient="true"/>
<ioread sourceClass="SiPixelCluster" version="[11-12]" targetClass="SiPixelCluster" source="uint16_t thePixelCol" target="theMinPixelCol">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ void SiPixelDigisClustersFromSoA::produce(edm::StreamID, edm::Event& iEvent, con
auto const & acluster = aclusters[ic];
if ( acluster.charge < clusterThreshold) continue;
SiPixelCluster cluster(acluster.isize,acluster.adc, acluster.x,acluster.y, acluster.xmin,acluster.ymin);
cluster.setOriginalId(ic);
++totCluseFilled;
// std::cout << "putting in this cluster " << ic << " " << cluster.charge() << " " << cluster.pixelADC().size() << endl;
// sort by row (x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class SiPixelRawToClusterCUDA: public edm::stream::EDProducer<edm::ExternalWork>
const bool includeErrors_;
const bool useQuality_;
const bool usePilotBlade_;
const bool convertADCtoElectrons_;
};

SiPixelRawToClusterCUDA::SiPixelRawToClusterCUDA(const edm::ParameterSet& iConfig):
Expand All @@ -77,8 +76,7 @@ SiPixelRawToClusterCUDA::SiPixelRawToClusterCUDA(const edm::ParameterSet& iConfi
cablingMapLabel_(iConfig.getParameter<std::string>("CablingMapLabel")),
includeErrors_(iConfig.getParameter<bool>("IncludeErrors")),
useQuality_(iConfig.getParameter<bool>("UseQualityInfo")),
usePilotBlade_(iConfig.getParameter<bool> ("UsePilotBlade")), // Control the usage of pilot-blade data, FED=40
convertADCtoElectrons_(iConfig.getParameter<bool>("ConvertADCtoElectrons"))
usePilotBlade_(iConfig.getParameter<bool> ("UsePilotBlade")) // Control the usage of pilot-blade data, FED=40
{
if(includeErrors_) {
digiErrorPutToken_ = produces<CUDAProduct<SiPixelDigiErrorsCUDA>>();
Expand All @@ -97,7 +95,6 @@ void SiPixelRawToClusterCUDA::fillDescriptions(edm::ConfigurationDescriptions& d
desc.add<bool>("IncludeErrors",true);
desc.add<bool>("UseQualityInfo",false);
desc.add<bool>("UsePilotBlade",false)->setComment("## Use pilot blades");
desc.add<bool>("ConvertADCtoElectrons", false)->setComment("## do the calibration ADC-> Electron and apply the threshold, requried for clustering");
desc.add<edm::InputTag>("InputLabel",edm::InputTag("rawDataCollector"));
{
edm::ParameterSetDescription psd0;
Expand Down Expand Up @@ -220,7 +217,7 @@ void SiPixelRawToClusterCUDA::acquire(const edm::Event& iEvent, const edm::Event
gpuAlgo_.makeClustersAsync(gpuMap, gpuModulesToUnpack, gpuGains,
wordFedAppender,
std::move(errors_),
wordCounterGPU, fedCounter, convertADCtoElectrons_,
wordCounterGPU, fedCounter,
useQuality_, includeErrors_,
edm::MessageDrop::instance()->debugEnabled,
ctx.stream());
Expand Down
Loading

0 comments on commit 8b4a4ab

Please sign in to comment.