| 663 | } |
| 664 | |
| 665 | StatusOr<EngineContext*> TRTEngineOp::GetEngine( |
| 666 | const std::vector<TensorShape>& input_shapes, OpKernelContext* ctx, |
| 667 | TRTEngineCacheResource* cache_res) { |
| 668 | static EngineContext empty_context; |
| 669 | |
| 670 | mutex_lock lock(engine_mutex_); |
| 671 | // Using first input to get batch size is reliable - VerifyInputShapes() has |
| 672 | // verified that. |
| 673 | const int batch_size = input_shapes[0].dim_size(0); |
| 674 | auto& cache = cache_res->cache_; |
| 675 | auto allocator = cache_res->allocator_.get(); |
| 676 | if (allocator == nullptr) { |
| 677 | return &empty_context; |
| 678 | } |
| 679 | |
| 680 | // Handle the static engine case. For static engines, the cache will have a |
| 681 | // single element containing the only engine. |
| 682 | if (static_engine_) { |
| 683 | if (cache.size()) { |
| 684 | if (AreShapesCompatible(input_shapes, cache.begin()->first)) { |
| 685 | return cache.begin()->second.get(); |
| 686 | } |
| 687 | return &empty_context; |
| 688 | } |
| 689 | |
| 690 | TrtUniquePtrType<IRuntime> infer(nvinfer1::createInferRuntime(logger)); |
| 691 | infer->setGpuAllocator(allocator); |
| 692 | TrtUniquePtrType<nvinfer1::ICudaEngine> static_engine( |
| 693 | infer->deserializeCudaEngine(serialized_segment_.c_str(), |
| 694 | serialized_segment_.size(), nullptr)); |
| 695 | auto raw_static_engine = static_engine.get(); |
| 696 | const auto max_batch_size = raw_static_engine->getMaxBatchSize(); |
| 697 | // Static engine will have max_batch_size for batch size so that all inputs |
| 698 | // will map to this single engine. |
| 699 | std::vector<TensorShape> engine_input_shapes(input_shapes); |
| 700 | for (int i = 0; i < engine_input_shapes.size(); i++) { |
| 701 | // TODO(tmorris): will all inputs have batch size as first dimension?? |
| 702 | engine_input_shapes[i].set_dim(0, max_batch_size); |
| 703 | } |
| 704 | // TODO(laigd): here we assume engine_input_shapes matches the actual input |
| 705 | // shapes of the engine, we should verify that. |
| 706 | cache.emplace(engine_input_shapes, |
| 707 | absl::make_unique<EngineContext>( |
| 708 | std::move(static_engine), |
| 709 | TrtUniquePtrType<nvinfer1::IExecutionContext>( |
| 710 | raw_static_engine->createExecutionContext()))); |
| 711 | // Runtime is safe to delete after engine creation |
| 712 | VLOG(1) << "Size of serialized TRT engine: " |
| 713 | << serialized_segment_.capacity(); |
| 714 | string tmp; |
| 715 | // Swap with temporary empty string to deallocate the CPU memory. |
| 716 | serialized_segment_.swap(tmp); |
| 717 | if (max_batch_size < batch_size) { |
| 718 | return &empty_context; |
| 719 | } |
| 720 | return cache.at(engine_input_shapes).get(); |
| 721 | } // static_engine_ |
| 722 |
no test coverage detected