#include #include "NvInfer.h" #include "NetworkRT.h" using namespace nvinfer1; #include "pluginsRT/ActivationLeakyRT.cpp" // Logger for info/warning/errors class Logger : public ILogger { void log(Severity severity, const char* msg) override { std::cout <<"TENSORRT: "<< msg << std::endl; } } loggerRT; namespace tkDNN { NetworkRT::NetworkRT(Network *net) { builderRT = createInferBuilder(loggerRT); networkRT = builderRT->createNetwork(); dtRT = DataType::kFLOAT; //add input layer dataDim_t dim = net->layers[0]->input_dim; ITensor *input = networkRT->addInput("data", dtRT, DimsCHW{ dim.c, dim.h, dim.w}); checkNULL(input); //add other layers for(int i=0; inum_layers; i++) { Layer *l = net->layers[i]; input = convert_layer(input, l); } if(input == NULL) FatalError("conversion failed"); output_dim = net->layers[net->num_layers-1]->output_dim; //build tensorRT input->setName("out"); networkRT->markOutput(*input); // Build the engine builderRT->setMaxBatchSize(1); builderRT->setMaxWorkspaceSize(1 << 20); std::cout<<"BUILD cuda engine\n"; engineRT = builderRT->buildCudaEngine(*networkRT); // we don't need the network any more //networkRT->destroy(); std::cout<<"create execution context\n"; contextRT = engineRT->createExecutionContext(); // input and output buffer pointers that we pass to the engine - the engine requires exactly IEngine::getNbBindings(), // of these, but in this case we know that there is exactly one input and one output. if(engineRT->getNbBindings() != 2) FatalError("Incorrect buffers number"); // In order to bind the buffers, we need to know the names of the input and output tensors. // note that indices are guaranteed to be less than IEngine::getNbBindings() buf_input_idx = engineRT->getBindingIndex("data"); buf_output_idx = engineRT->getBindingIndex("out"); std::cout<<"input idex = "< output index = "<enqueue(1, buffersRT, stream, nullptr); checkCuda(cudaMemcpyAsync(output, buffersRT[buf_output_idx], output_dim.tot()*sizeof(float), cudaMemcpyDeviceToDevice, stream)); cudaStreamSynchronize(stream); dim = output_dim; return output; } ITensor* NetworkRT::convert_layer(ITensor *input, Layer *l) { layerType_t type = l->getLayerType(); if(type == LAYER_DENSE) return convert_layer(input, (Dense*) l); if(type == LAYER_CONV2D) return convert_layer(input, (Conv2d*) l); if(type == LAYER_POOLING) return convert_layer(input, (Pooling*) l); if(type == LAYER_ACTIVATION) return convert_layer(input, (Activation*) l); if(type == LAYER_SOFTMAX) return convert_layer(input, (Softmax*) l); FatalError("Layer not implemented in tensorRT"); return NULL; } ITensor* NetworkRT::convert_layer(ITensor *input, Dense *l) { std::cout<<"convert Dense\n"; Weights w { dtRT, l->data_h, l->inputs*l->outputs}; Weights b = { dtRT, l->bias_h, l->outputs}; IFullyConnectedLayer *lRT = networkRT->addFullyConnected(*input, l->outputs, w, b); checkNULL(lRT); return lRT->getOutput(0); } ITensor* NetworkRT::convert_layer(ITensor *input, Conv2d *l) { std::cout<<"convert conv2D\n"; Weights w { dtRT, l->data_h, l->inputs*l->outputs*l->kernelH*l->kernelW}; Weights b; if(!l->batchnorm) b = { dtRT, l->bias_h, l->outputs}; else b = { dtRT, nullptr, 0}; //on batchnorm bias are added later // Add a convolution layer with 20 outputs and a 5x5 filter. IConvolutionLayer *lRT = networkRT->addConvolution(*input, l->outputs, DimsHW{l->kernelH, l->kernelW}, w, b); checkNULL(lRT); lRT->setStride(DimsHW{l->strideH, l->strideW}); lRT->setPadding(DimsHW{l->paddingH, l->paddingW}); if(l->batchnorm) { float eps = CUDNN_BN_MIN_EPSILON; //make power array of ones value_type *power_h = new value_type[l->outputs]; for(int i=0; ioutputs; i++) power_h[i] = 1.0f; //convert mean for(int i=0; ioutputs; i++) l->mean_h[i] = l->mean_h[i] / -sqrt(eps + l->variance_h[i]); //convert variance for(int i=0; ioutputs; i++) l->variance_h[i] = 1.0f / sqrt(eps + l->variance_h[i]); Weights power{dtRT, power_h, l->outputs}; Weights shift{dtRT, l->mean_h, l->outputs}; Weights scale{dtRT, l->variance_h, l->outputs}; IScaleLayer *lRT2 = networkRT->addScale(*lRT->getOutput(0), ScaleMode::kCHANNEL, shift, scale, power); checkNULL(lRT2); Weights shift2{dtRT, l->bias_h, l->outputs}; Weights scale2{dtRT, l->scales_h, l->outputs}; IScaleLayer *lRT3 = networkRT->addScale(*lRT2->getOutput(0), ScaleMode::kCHANNEL, shift2, scale2, power); checkNULL(lRT3); return lRT3->getOutput(0); } return lRT->getOutput(0); } ITensor* NetworkRT::convert_layer(ITensor *input, Pooling *l) { std::cout<<"convert Pooling\n"; IPoolingLayer *lRT = networkRT->addPooling(*input, PoolingType::kMAX, DimsHW{l->winH, l->winW}); checkNULL(lRT); lRT->setStride(DimsHW{l->strideH, l->strideW}); return lRT->getOutput(0); } ITensor* NetworkRT::convert_layer(ITensor *input, Activation *l) { std::cout<<"convert Activation\n"; if(l->act_mode == ACTIVATION_LEAKY) { std::cout<<"New plugin LEAKY\n"; IPlugin *plugin = new ActivationLeakyRT(); IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin); checkNULL(lRT); return lRT->getOutput(0); } IActivationLayer *lRT = networkRT->addActivation(*input, ActivationType::kRELU); checkNULL(lRT); return lRT->getOutput(0); } ITensor* NetworkRT::convert_layer(ITensor *input, Softmax *l) { std::cout<<"convert softmax\n"; ISoftMaxLayer *lRT = networkRT->addSoftMax(*input); checkNULL(lRT); return lRT->getOutput(0); } }