|
|
|
|
@ -22,14 +22,18 @@
|
|
|
|
|
|
|
|
|
|
namespace paddle {
|
|
|
|
|
namespace inference {
|
|
|
|
|
|
|
|
|
|
DEFINE_int32(tensorrt_max_batchsize, 300, "TensorRT maximum batch size");
|
|
|
|
|
DEFINE_int32(tensorrt_workspace_size, 2048, "TensorRT workspace size");
|
|
|
|
|
|
|
|
|
|
namespace analysis {
|
|
|
|
|
|
|
|
|
|
using framework::proto::ProgramDesc;
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> ExtractParameters(
|
|
|
|
|
const std::vector<std::unique_ptr<Node>>& nodes);
|
|
|
|
|
const std::vector<std::unique_ptr<Node>> &nodes);
|
|
|
|
|
|
|
|
|
|
bool DataFlowGraphToFluidPass::Initialize(Argument* argument) {
|
|
|
|
|
bool DataFlowGraphToFluidPass::Initialize(Argument *argument) {
|
|
|
|
|
ANALYSIS_ARGUMENT_CHECK_FIELD(argument)
|
|
|
|
|
ANALYSIS_ARGUMENT_CHECK_FIELD(argument->origin_program_desc)
|
|
|
|
|
PADDLE_ENFORCE(!argument->transformed_program_desc);
|
|
|
|
|
@ -47,76 +51,77 @@ bool DataFlowGraphToFluidPass::Initialize(Argument* argument) {
|
|
|
|
|
|
|
|
|
|
bool DataFlowGraphToFluidPass::Finalize() { return true; }
|
|
|
|
|
|
|
|
|
|
void DataFlowGraphToFluidPass::Run(DataFlowGraph* graph) {
|
|
|
|
|
auto traits = GraphTraits<DataFlowGraph>(graph);
|
|
|
|
|
for (auto it = traits.nodes().begin(); it != traits.nodes().end(); ++it) {
|
|
|
|
|
if (it->deleted()) continue;
|
|
|
|
|
void DataFlowGraphToFluidPass::Run(DataFlowGraph *graph) {
|
|
|
|
|
LOG(INFO) << "graph.inputs " << graph->inputs.size();
|
|
|
|
|
for (auto &node : GraphTraits<DataFlowGraph>(graph).nodes_in_TS()) {
|
|
|
|
|
if (node.deleted()) continue;
|
|
|
|
|
|
|
|
|
|
switch (it->type()) {
|
|
|
|
|
switch (node.type()) {
|
|
|
|
|
case Node::Type::kFunction: {
|
|
|
|
|
LOG(INFO) << "add function " << it->repr();
|
|
|
|
|
AddFluidOp(&(*it));
|
|
|
|
|
LOG(INFO) << "add function " << node.repr();
|
|
|
|
|
AddFluidOp(&node);
|
|
|
|
|
} break;
|
|
|
|
|
case Node::Type::kFunctionBlock: {
|
|
|
|
|
LOG(INFO) << "add engine op " << it->repr() << " , "
|
|
|
|
|
<< static_cast<FunctionBlock*>(&(*it))->subgraph.size();
|
|
|
|
|
AddEngineOp(&(*it));
|
|
|
|
|
LOG(INFO) << "add engine op " << node.repr() << " , "
|
|
|
|
|
<< static_cast<FunctionBlock *>(&node)->subgraph.size();
|
|
|
|
|
AddEngineOp(&node);
|
|
|
|
|
} break;
|
|
|
|
|
default:
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(argument_->transformed_program_desc.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DataFlowGraphToFluidPass::AddFluidOp(Node* node) {
|
|
|
|
|
auto* ori_op = static_cast<framework::proto::OpDesc*>(node->pb_desc());
|
|
|
|
|
void DataFlowGraphToFluidPass::AddFluidOp(Node *node) {
|
|
|
|
|
auto *ori_op = static_cast<framework::proto::OpDesc *>(node->pb_desc());
|
|
|
|
|
// currently only the main block is analyzed.
|
|
|
|
|
auto* main_block = desc_->mutable_blocks(framework::kRootBlockIndex);
|
|
|
|
|
auto* op = main_block->add_ops();
|
|
|
|
|
auto *main_block = desc_->mutable_blocks(framework::kRootBlockIndex);
|
|
|
|
|
auto *op = main_block->add_ops();
|
|
|
|
|
*op = *ori_op; // copy the attributes, by default, these will not be changed
|
|
|
|
|
// by analysis phrase.
|
|
|
|
|
// by analysis phrase.
|
|
|
|
|
// The inputs and outputs of the existing ops are not changed by tensorrt
|
|
|
|
|
// subgraph pass.
|
|
|
|
|
// NOTE It might be changed by other passes in the long run.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CreateTrtEngineOp(Node* node, const DataFlowGraph& graph,
|
|
|
|
|
const framework::proto::BlockDesc& block) {
|
|
|
|
|
void CreateTrtEngineOp(Node *node, const DataFlowGraph &graph,
|
|
|
|
|
const framework::proto::BlockDesc &block) {
|
|
|
|
|
static int counter{0};
|
|
|
|
|
PADDLE_ENFORCE(node->IsFunctionBlock());
|
|
|
|
|
framework::OpDesc desc;
|
|
|
|
|
auto* func = static_cast<FunctionBlock*>(node);
|
|
|
|
|
auto *func = static_cast<FunctionBlock *>(node);
|
|
|
|
|
|
|
|
|
|
// collect inputs
|
|
|
|
|
std::vector<std::string> io;
|
|
|
|
|
for (auto* x : func->inlinks) {
|
|
|
|
|
for (auto *x : func->inlinks) {
|
|
|
|
|
io.push_back(x->name());
|
|
|
|
|
}
|
|
|
|
|
desc.SetInput("Xs", io);
|
|
|
|
|
|
|
|
|
|
// collect outputs
|
|
|
|
|
io.clear();
|
|
|
|
|
for (auto* x : func->outlinks) {
|
|
|
|
|
for (auto *x : func->outlinks) {
|
|
|
|
|
io.push_back(x->name());
|
|
|
|
|
}
|
|
|
|
|
desc.SetOutput("Ys", io);
|
|
|
|
|
|
|
|
|
|
desc.SetType("tensorrt_engine");
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(!block.vars().empty(), "the block has no var-desc");
|
|
|
|
|
// Set attrs
|
|
|
|
|
SetAttr(desc.Proto(), "subgraph", block.SerializeAsString());
|
|
|
|
|
SetAttr(desc.Proto(), "engine_unique_key",
|
|
|
|
|
"trt-" + std::to_string(counter++));
|
|
|
|
|
SetAttr(desc.Proto(), "max_batch", 100); // TODO(Superjomn) add config latter
|
|
|
|
|
SetAttr(desc.Proto(), "max_workspace",
|
|
|
|
|
1024); // TODO(Superjomn) add config latter
|
|
|
|
|
SetAttr(desc.Proto(), "engine_uniq_key", "trt-" + std::to_string(counter++));
|
|
|
|
|
SetAttr(desc.Proto(), "max_batch", FLAGS_tensorrt_max_batchsize);
|
|
|
|
|
SetAttr(desc.Proto(), "max_workspace", FLAGS_tensorrt_workspace_size);
|
|
|
|
|
SetAttr(desc.Proto(), "parameters", ExtractParameters(graph.nodes.nodes()));
|
|
|
|
|
node->SetPbMsg(desc.Proto()->SerializeAsString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> ExtractParameters(
|
|
|
|
|
const std::vector<std::unique_ptr<Node>>& nodes) {
|
|
|
|
|
const std::vector<std::unique_ptr<Node>> &nodes) {
|
|
|
|
|
std::vector<std::string> parameters;
|
|
|
|
|
for (const auto& node : nodes) {
|
|
|
|
|
for (const auto &node : nodes) {
|
|
|
|
|
if (!node->IsValue()) continue;
|
|
|
|
|
PADDLE_ENFORCE(!node->pb_msg().empty(), "pb_msg should be set first");
|
|
|
|
|
framework::proto::VarDesc var;
|
|
|
|
|
@ -128,21 +133,30 @@ std::vector<std::string> ExtractParameters(
|
|
|
|
|
return parameters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DataFlowGraphToFluidPass::AddEngineOp(Node* node) {
|
|
|
|
|
void DataFlowGraphToFluidPass::AddEngineOp(Node *node) {
|
|
|
|
|
// TODO(Superjomn) Here need to expose some arguments for default setting.
|
|
|
|
|
PADDLE_ENFORCE(node->IsFunctionBlock());
|
|
|
|
|
auto* block_node = static_cast<FunctionBlock*>(node);
|
|
|
|
|
auto *block_node = static_cast<FunctionBlock *>(node);
|
|
|
|
|
framework::proto::BlockDesc proto;
|
|
|
|
|
framework::BlockDesc block_desc(nullptr, &proto);
|
|
|
|
|
block_desc.Proto()->set_parent_idx(-1);
|
|
|
|
|
block_desc.Proto()->set_idx(0);
|
|
|
|
|
LOG(INFO) << "origin variable size: "
|
|
|
|
|
<< argument_->origin_program_desc->blocks(0).vars().size();
|
|
|
|
|
LOG(INFO) << "transformed variable size: "
|
|
|
|
|
<< block_desc.Proto()->vars().size();
|
|
|
|
|
// copy ops.
|
|
|
|
|
for (auto* node : block_node->subgraph) {
|
|
|
|
|
auto* op = block_desc.AppendOp();
|
|
|
|
|
for (auto *node : block_node->subgraph) {
|
|
|
|
|
auto *op = block_desc.AppendOp();
|
|
|
|
|
PADDLE_ENFORCE(!node->pb_msg().empty());
|
|
|
|
|
op->Proto()->ParseFromString(node->pb_msg());
|
|
|
|
|
}
|
|
|
|
|
*block_desc.Proto()->mutable_vars() =
|
|
|
|
|
argument_->origin_program_desc->blocks(0).vars();
|
|
|
|
|
PADDLE_ENFORCE(!block_desc.Proto()->vars().empty());
|
|
|
|
|
CreateTrtEngineOp(node, *argument_->main_dfg, *block_desc.Proto());
|
|
|
|
|
auto* main_block = desc_->mutable_blocks(framework::kRootBlockIndex);
|
|
|
|
|
auto* op = main_block->add_ops();
|
|
|
|
|
auto *main_block = desc_->mutable_blocks(framework::kRootBlockIndex);
|
|
|
|
|
auto *op = main_block->add_ops();
|
|
|
|
|
PADDLE_ENFORCE(!node->pb_msg().empty(), "failed to set desc for block");
|
|
|
|
|
op->ParseFromString(node->pb_msg());
|
|
|
|
|
}
|
|
|
|
|
@ -151,7 +165,7 @@ namespace {
|
|
|
|
|
class DFG_DebuggerPass : public DFG_GraphvizDrawPass {
|
|
|
|
|
public:
|
|
|
|
|
using Config = DFG_GraphvizDrawPass::Config;
|
|
|
|
|
explicit DFG_DebuggerPass(const Config& config)
|
|
|
|
|
explicit DFG_DebuggerPass(const Config &config)
|
|
|
|
|
: DFG_GraphvizDrawPass(config) {}
|
|
|
|
|
|
|
|
|
|
std::string repr() const override { return "dfg-to-fluid-debuger-pass"; }
|
|
|
|
|
@ -160,7 +174,7 @@ class DFG_DebuggerPass : public DFG_GraphvizDrawPass {
|
|
|
|
|
};
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
Pass* DataFlowGraphToFluidPass::CreateGraphvizDebugerPass() const {
|
|
|
|
|
Pass *DataFlowGraphToFluidPass::CreateGraphvizDebugerPass() const {
|
|
|
|
|
return new DFG_DebuggerPass(DFG_GraphvizDrawPass::Config(
|
|
|
|
|
FLAGS_inference_analysis_graphviz_log_root,
|
|
|
|
|
"data_flow_graph_to_fluid_graphviz_debugger"));
|
|
|
|
|
|