Skip to content

Commit 669adf8

Browse files
violatingcpkpedro88
authored andcommitted
added FPGA and some small bug fixes
1 parent ff1b4cf commit 669adf8

File tree

6 files changed

+456
-10
lines changed

6 files changed

+456
-10
lines changed

TensorRT/interface/TRTClient.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class TRTClient : public Client {
5555

5656
protected:
5757
void predictImpl() override;
58-
58+
bool fSetup;
5959
//helper for common ops
6060
void setup();
6161

TensorRT/interface/TRTClientFPGA.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef SonicCMS_TensorRT_TRTClientFPGA
2+
#define SonicCMS_TensorRT_TRTClientFPGA
3+
4+
#include "FWCore/ParameterSet/interface/ParameterSet.h"
5+
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
6+
#include "SonicCMS/Core/interface/SonicClientSync.h"
7+
#include "SonicCMS/Core/interface/SonicClientPseudoAsync.h"
8+
#include "SonicCMS/Core/interface/SonicClientAsync.h"
9+
10+
#include <vector>
11+
#include <string>
12+
13+
#include "request_grpc.h"
14+
15+
namespace nic = nvidia::inferenceserver::client;
16+
17+
template <typename Client>
18+
class TRTClientFPGA : public Client {
19+
public:
20+
//constructor
21+
TRTClientFPGA(const edm::ParameterSet& params);
22+
23+
//helper
24+
void getResults(const std::unique_ptr<nic::InferContext::Result>& result);
25+
26+
//accessors
27+
unsigned ninput() const { return ninput_; }
28+
unsigned noutput() const { return noutput_; }
29+
unsigned batchSize() const { return batchSize_; }
30+
31+
//for fillDescriptions
32+
static void fillPSetDescription(edm::ParameterSetDescription& iDesc) {
33+
edm::ParameterSetDescription descClient;
34+
descClient.add<unsigned>("ninput");
35+
descClient.add<unsigned>("noutput");
36+
descClient.add<unsigned>("batchSize");
37+
descClient.add<std::string>("address");
38+
descClient.add<unsigned>("port");
39+
descClient.add<unsigned>("timeout");
40+
descClient.add<std::string>("modelName");
41+
iDesc.add<edm::ParameterSetDescription>("Client",descClient);
42+
}
43+
44+
protected:
45+
void predictImpl() override;
46+
bool fSetup;
47+
//helper for common ops
48+
void setup();
49+
50+
//members
51+
std::string url_;
52+
unsigned timeout_;
53+
std::string modelName_;
54+
unsigned batchSize_;
55+
unsigned ninput_;
56+
unsigned noutput_;
57+
std::unique_ptr<nic::InferContext> context_;
58+
std::shared_ptr<nic::InferContext::Input> nicinput_;
59+
};
60+
typedef TRTClientFPGA<SonicClientSync<std::vector<unsigned short>>> TRTClientFPGASync;
61+
typedef TRTClientFPGA<SonicClientPseudoAsync<std::vector<unsigned short>>> TRTClientFPGAPseudoAsync;
62+
typedef TRTClientFPGA<SonicClientAsync<std::vector<unsigned short>>> TRTClientFPGAAsync;
63+
64+
#endif
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include <vector>
2+
#include <map>
3+
#include <sstream>
4+
#include <string>
5+
#include <fstream>
6+
7+
#include "SonicCMS/Core/interface/SonicEDProducer.h"
8+
#include "SonicCMS/TensorRT/interface/TRTClientFPGA.h"
9+
#include "FWCore/Framework/interface/Event.h"
10+
#include "FWCore/ParameterSet/interface/ParameterSet.h"
11+
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
12+
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
13+
#include "FWCore/Framework/interface/EventSetup.h"
14+
#include "FWCore/Framework/interface/Frameworkfwd.h"
15+
#include "FWCore/Framework/interface/MakerMacros.h"
16+
#include "FWCore/MessageLogger/interface/MessageLogger.h"
17+
18+
template <typename Client>
19+
class HcalProducerFPGA : public SonicEDProducer<Client>
20+
{
21+
public:
22+
//needed because base class has dependent scope
23+
using typename SonicEDProducer<Client>::Input;
24+
using typename SonicEDProducer<Client>::Output;
25+
//std::vector<float> fInVals; => debug
26+
//std::vector<float> fPrVals;
27+
//int fCount;
28+
explicit HcalProducerFPGA(edm::ParameterSet const& cfg) : SonicEDProducer<Client>(cfg), topN_(cfg.getParameter<unsigned>("topN")) {
29+
//for debugging
30+
this->setDebugName("HcalProducerFPGA");
31+
/* Validation on temporary files
32+
std::ifstream lFIn("tb_input_features.dat");
33+
std::ifstream lFPr("tb_output_predictions.dat");
34+
std::string iline;
35+
std::string pline;
36+
bool hit_end = false;
37+
bool valid_data = true;
38+
for (int istream = 0; istream < 16000; istream++) {
39+
if (valid_data && !hit_end){
40+
if(std::getline(lFIn,iline) && std::getline(lFPr,pline)) {
41+
char* cstr=const_cast<char*>(iline.c_str());
42+
char* current;
43+
std::vector<float> in;
44+
current=strtok(cstr," ");
45+
while(current!=NULL){
46+
fInVals.push_back(atof(current));
47+
current=strtok(NULL," ");
48+
}
49+
cstr=const_cast<char*>(pline.c_str());
50+
current=strtok(cstr," ");
51+
while(current!=NULL){
52+
fPrVals.push_back(atof(current));
53+
current=strtok(NULL," ");
54+
}
55+
}
56+
}
57+
}
58+
fCount = 0;
59+
*/
60+
61+
}
62+
void acquire(edm::Event const& iEvent, edm::EventSetup const& iSetup, Input& iInput) override {
63+
auto ninput = client_.ninput();
64+
auto batchSize = client_.batchSize();
65+
iInput = Input(ninput*batchSize, 0.f);
66+
//make some random channels
67+
for(unsigned ib = 0; ib < batchSize; ib++) {
68+
//Current Hcal setup takes 11 inputs but it is sent in chunks of 16 to the FPGA
69+
iInput[ib*ninput+0] = f_to_ui<16,6>(1);
70+
iInput[ib*ninput+1] = f_to_ui<16,6>(2);
71+
iInput[ib*ninput+3] = f_to_ui<16,6>(int(rand() % 30)-15);
72+
iInput[ib*ninput+4] = f_to_ui<16,6>(int(rand() % 36)-36);
73+
for(unsigned i0 = 5; i0 < 18; i0++) iInput[ib*ninput+i0] = f_to_ui<16,8>(1);
74+
for(unsigned i0 = 18; i0 < ninput; i0++) iInput[ib*ninput+i0] = f_to_ui<16,8>(0);
75+
/* for debug
76+
for(unsigned i0 = 0; i0 < 11; i0++) iInput[ib*ninput+i0] = f_to_ui<32,14>(fInVals[i0+11*fCount]);
77+
for(unsigned i0 = 11; i0 < ninput; i0++) iInput[ib*ninput+i0] = 0;
78+
fCount++;
79+
*/
80+
}
81+
}
82+
void produce(edm::Event& iEvent, edm::EventSetup const& iSetup, Output const& iOutput) override {
83+
//check the results
84+
findTopN(iOutput);
85+
}
86+
~HcalProducerFPGA() override {}
87+
//to ensure distinct cfi names - specialized below
88+
static std::string getCfiName();
89+
static void fillDescriptions(edm::ConfigurationDescriptions & descriptions) {
90+
edm::ParameterSetDescription desc;
91+
Client::fillPSetDescription(desc);
92+
desc.add<unsigned>("topN",5);
93+
descriptions.add(getCfiName(),desc);
94+
}
95+
//Just putting something in for the hell of it
96+
void findTopN(const Output& scores) const {
97+
auto dim = client_.noutput();
98+
//int batchsize = client_.batchSize();
99+
for(unsigned i0 = 0; i0 < client_.batchSize(); i0++) {
100+
//match score to type by index, then put in largest-first map
101+
std::map<float,std::string,std::greater<float>> score_map;
102+
for(unsigned i = 0; i < (unsigned)dim; ++i){
103+
std::stringstream pSS; pSS << "Dummy Channel " << i;
104+
score_map.emplace(scores[i0*dim+i],pSS.str());
105+
}
106+
//get top n
107+
std::stringstream msg;
108+
msg << "Scores:\n";
109+
unsigned counter = 0;
110+
for(const auto& item: score_map){
111+
msg << item.second << " : " << item.first << "\n";
112+
++counter;
113+
if(counter>=topN_) break;
114+
}
115+
edm::LogInfo("HcalProducerFPGA") << msg.str();
116+
}
117+
}
118+
119+
120+
private:
121+
using SonicEDProducer<Client>::client_;
122+
template<unsigned int B, unsigned int I>
123+
unsigned short f_to_ui(float f) {
124+
bool isPos = f > 0.;
125+
short tmpIs = int(fabs(f));
126+
unsigned short tmpI = tmpIs;
127+
if (not isPos) {
128+
//unsigned int comp = ((unsigned int)((1<<(sizeof(unsigned int)*8-I+1))-1)<<I);
129+
unsigned short comp = ((unsigned short)((1<<(sizeof(unsigned short)*4-I+1))-1)<<I);
130+
tmpI = -tmpIs;
131+
tmpI = tmpI-comp;
132+
}
133+
float tmpF = fabs(f) - float(tmpIs);
134+
unsigned short fracs = tmpF*float(1<<(B-I));
135+
unsigned short val = (tmpI << (B-I)) + fracs;
136+
return val;
137+
}
138+
template<unsigned int B, unsigned int I>
139+
float ui_to_f(const unsigned short ui) {
140+
unsigned short i = ui >> (B-I);
141+
unsigned short mask = (1 << (B-I))-1;
142+
unsigned short dec = ui & mask;
143+
float lDec = float(dec)/float(1 << (B-I));
144+
return float(i)+lDec;
145+
}
146+
uint32_t merge(unsigned short iA,unsigned short iB) {
147+
uint32_t result = (uint32_t) iA << 16 | iB;
148+
return result;
149+
}
150+
unsigned topN_;
151+
};
152+
153+
typedef HcalProducerFPGA<TRTClientFPGASync> HcalProducerFPGASync;
154+
typedef HcalProducerFPGA<TRTClientFPGAAsync> HcalProducerFPGAAsync;
155+
typedef HcalProducerFPGA<TRTClientFPGAPseudoAsync> HcalProducerFPGAPseudoAsync;
156+
157+
template<> std::string HcalProducerFPGASync::getCfiName() { return "HcalProducerFPGASync"; }
158+
template<> std::string HcalProducerFPGAAsync::getCfiName() { return "HcalProducerFPGAAsync"; }
159+
template<> std::string HcalProducerFPGAPseudoAsync::getCfiName() { return "HcalProducerFPGAPseudoAsync"; }
160+
161+
DEFINE_FWK_MODULE(HcalProducerFPGASync);
162+
DEFINE_FWK_MODULE(HcalProducerFPGAAsync);
163+
DEFINE_FWK_MODULE(HcalProducerFPGAPseudoAsync);
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from FWCore.ParameterSet.VarParsing import VarParsing
2+
import FWCore.ParameterSet.Config as cms
3+
import os, sys, json
4+
5+
options = VarParsing("analysis")
6+
#options.register("address", "ailab01.fnal.gov", VarParsing.multiplicity.singleton, VarParsing.varType.string)
7+
#options.register("address", "prp-gpu-1.t2.ucsd.edu", VarParsing.multiplicity.singleton, VarParsing.varType.string)
8+
#options.register("address", "18.4.112.82", VarParsing.multiplicity.singleton, VarParsing.varType.string)
9+
options.register("address", "18.237.83.169", VarParsing.multiplicity.singleton, VarParsing.varType.string)
10+
options.register("port", 8443, VarParsing.multiplicity.singleton, VarParsing.varType.int)
11+
options.register("timeout", 30, VarParsing.multiplicity.singleton, VarParsing.varType.int)
12+
options.register("params", "", VarParsing.multiplicity.singleton, VarParsing.varType.string)
13+
options.register("threads", 1, VarParsing.multiplicity.singleton, VarParsing.varType.int)
14+
options.register("streams", 1, VarParsing.multiplicity.singleton, VarParsing.varType.int)
15+
options.register("batchsize", 16000, VarParsing.multiplicity.singleton, VarParsing.varType.int)
16+
options.register("modelname","facile", VarParsing.multiplicity.singleton, VarParsing.varType.string)
17+
options.register("mode", "Async", VarParsing.multiplicity.singleton, VarParsing.varType.string)
18+
options.parseArguments()
19+
20+
if len(options.params)>0:
21+
with open(options.params,'r') as pfile:
22+
pdict = json.load(pfile)
23+
options.address = pdict["address"]
24+
options.port = int(pdict["port"])
25+
print("server = "+options.address+":"+str(options.port))
26+
27+
# check mode
28+
allowed_modes = {
29+
"Async": "HcalProducerFPGAAsync",
30+
"Sync": "HcalProducerFPGASync",
31+
"PseudoAsync": "HcalProducerPseudoFPGAAsync",
32+
}
33+
if options.mode not in allowed_modes:
34+
raise ValueError("Unknown mode: "+options.mode)
35+
36+
process = cms.Process('imageTest')
37+
38+
#--------------------------------------------------------------------------------
39+
# Import of standard configurations
40+
#================================================================================
41+
process.load('FWCore/MessageService/MessageLogger_cfi')
42+
process.load('Configuration/StandardSequences/GeometryDB_cff')
43+
process.load('Configuration/StandardSequences/MagneticField_38T_cff')
44+
45+
#process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff")
46+
#process.GlobalTag.globaltag = cms.string('100X_upgrade2018_realistic_v10')
47+
48+
process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.maxEvents) )
49+
process.source = cms.Source("PoolSource",
50+
fileNames = cms.untracked.vstring('file:../../Core/data/store_mc_RunIISpring18MiniAOD_BulkGravTohhTohbbhbb_narrow_M-2000_13TeV-madgraph_MINIAODSIM_100X_upgrade2018_realistic_v10-v1_30000_24A0230C-B530-E811-ADE3-14187741120B.root')
51+
)
52+
53+
if len(options.inputFiles)>0: process.source.fileNames = options.inputFiles
54+
55+
################### EDProducer ##############################
56+
process.HcalProducer = cms.EDProducer(allowed_modes[options.mode],
57+
topN = cms.uint32(5),
58+
Client = cms.PSet(
59+
ninput = cms.uint32(32),
60+
noutput = cms.uint32(1),
61+
batchSize = cms.uint32(options.batchsize),
62+
address = cms.string(options.address),
63+
port = cms.uint32(options.port),
64+
timeout = cms.uint32(options.timeout),
65+
modelName = cms.string(options.modelname),
66+
)
67+
)
68+
69+
# Let it run
70+
process.p = cms.Path(
71+
process.HcalProducer
72+
)
73+
74+
process.MessageLogger.cerr.FwkReport.reportEvery = 1
75+
keep_msgs = ['TRTClient']#,'HcalProducerFPGA']
76+
for msg in keep_msgs:
77+
process.MessageLogger.categories.append(msg)
78+
setattr(process.MessageLogger.cerr,msg,
79+
cms.untracked.PSet(
80+
optionalPSet = cms.untracked.bool(True),
81+
limit = cms.untracked.int32(10000000),
82+
)
83+
)
84+
85+
if options.threads>0:
86+
if not hasattr(process,"options"):
87+
process.options = cms.untracked.PSet()
88+
process.options.numberOfThreads = cms.untracked.uint32(options.threads)
89+
process.options.numberOfStreams = cms.untracked.uint32(options.streams if options.streams>0 else 0)

TensorRT/src/TRTClient.cc

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,31 @@ TRTClient<Client>::TRTClient(const edm::ParameterSet& params) :
2525
ninput_(params.getParameter<unsigned>("ninput")),
2626
noutput_(params.getParameter<unsigned>("noutput"))
2727
{
28+
fSetup = false;
2829
}
2930

3031
template <typename Client>
3132
void TRTClient<Client>::setup() {
32-
auto err = nic::InferGrpcContext::Create(&context_, url_, modelName_, -1, false);
33-
if (!err.IsOk()) throw cms::Exception("BadGrpc") << "unable to create inference context: " << err;
33+
if(!fSetup) {
34+
auto err = nic::InferGrpcContext::Create(&context_, url_, modelName_, -1, false);
35+
if(!err.IsOk()) throw cms::Exception("BadGrpc") << "unable to create inference context: " << err;
3436

35-
std::unique_ptr<nic::InferContext::Options> options;
36-
nic::InferContext::Options::Create(&options);
37+
std::unique_ptr<nic::InferContext::Options> options;
38+
nic::InferContext::Options::Create(&options);
3739

38-
options->SetBatchSize(batchSize_);
39-
for (const auto& output : context_->Outputs()) {
40-
options->AddRawResult(output);
40+
options->SetBatchSize(batchSize_);
41+
for (const auto& output : context_->Outputs()) {
42+
options->AddRawResult(output);
43+
}
44+
context_->SetRunOptions(*options);
45+
46+
fSetup = true;
4147
}
42-
context_->SetRunOptions(*options);
4348

4449
const std::vector<std::shared_ptr<nic::InferContext::Input>>& nicinputs = context_->Inputs();
4550
nicinput_ = nicinputs[0];
4651
nicinput_->Reset();
47-
52+
4853
auto t2 = std::chrono::high_resolution_clock::now();
4954
std::vector<int64_t> input_shape;
5055
for(unsigned i0 = 0; i0 < batchSize_; i0++) {

0 commit comments

Comments
 (0)