chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
# skip win32 since wget is not installed by default on windows machine.
if(NOT WIN32)
paddle_test(standalone_executor_pir_test SRCS standalone_executor_pir_test.cc)
endif()
set(OPS
fill_constant_op
uniform_random_op
lookup_table_op
transpose_op
reshape_op
split_op
slice_op
concat_op
matmul_op
elementwise_add_op
elementwise_mul_op
softmax_with_cross_entropy_op
reduce_mean_op
activation_op
sum_op
elementwise_div_op
generated_op
generated_static_op
squared_l2_norm_op
memcpy_h2d_op
memcpy_d2h_op
fetch_v2_op)
if(WITH_GPU
AND WITH_TESTING
AND NOT WIN32)
add_custom_target(
download_program
COMMAND wget -nc --no-check-certificate
https://paddle-ci.gz.bcebos.com/new_exec/lm_main_program
COMMAND wget -nc --no-check-certificate
https://paddle-ci.gz.bcebos.com/new_exec/lm_startup_program
WORKING_DIRECTORY "${CC_TESTS_DIR}")
# all operators used in the program
# All deps of the operators above, part of GLOB_OPERATOR_DEPS.
set(OP_DEPS phi common cross_entropy)
cc_test(standalone_executor_test SRCS standalone_executor_test.cc)
# add_dependencies(standalone_executor_test download_program)
# if(WITH_PROFILER)
# target_link_libraries(standalone_executor_test profiler)
# add_dependencies(standalone_executor_test profiler)
# endif()
endif()
@@ -0,0 +1,389 @@
// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/framework/new_executor/standalone_executor.h"
#include <gtest/gtest.h>
#include <chrono>
#include <iostream>
#include <string>
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/fluid/framework/new_executor/pir_interpreter.h"
#include "paddle/fluid/pir/dialect/operator/ir/control_flow_op.h"
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
#include "paddle/fluid/pir/dialect/operator/ir/pd_op.h"
#include "paddle/fluid/pir/transforms/pd_op_to_kernel_pass.h"
#include "paddle/pir/include/core/builder.h"
#include "paddle/pir/include/core/ir_context.h"
#include "paddle/pir/include/core/program.h"
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
#include "paddle/common/macros.h"
#include "paddle/pir/include/dialect/control_flow/ir/cf_dialect.h"
#include "paddle/pir/include/dialect/control_flow/ir/cf_op.h"
DECLARE_FILE_SYMBOLS(kernel_dialect);
PD_DECLARE_KERNEL(full, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(full_int_array, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(uniform, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(add, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sqrt, CPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(less_than, CPU, ALL_LAYOUT);
bool simple_cmp(float a, float b) { return std::abs((a - b) / a) < 1e-5; }
namespace paddle {
namespace framework {
TEST(StandaloneExecutor, run) {
pir::IrContext* ctx = pir::IrContext::Instance();
pir::Program program((ctx));
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
pir::Builder builder = pir::Builder(ctx, program.block());
paddle::dialect::FullOp op1 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2, 2}, 1.0, phi::DataType::FLOAT32, phi::CPUPlace());
paddle::dialect::FullOp op2 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2, 2}, 1.0, phi::DataType::FLOAT32, phi::CPUPlace());
auto add_op =
builder.Build<paddle::dialect::AddOp>(op1->result(0), op2->result(0));
std::string out_name = "add_out";
builder.Build<pir::ShadowOutputOp>(add_op->result(0), out_name);
auto kernel_program = pir::PdOpLowerToKernelPass(&program);
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
test_core.Run({});
auto out_tensor =
test_core.local_scope() == nullptr
? scope.FindVar(out_name)->Get<phi::DenseTensor>()
: test_core.local_scope()->FindVar(out_name)->Get<phi::DenseTensor>();
bool res0 = simple_cmp(out_tensor.data<float>()[0], 2.0);
bool res1 = simple_cmp(out_tensor.data<float>()[1], 2.0);
bool res2 = simple_cmp(out_tensor.data<float>()[2], 2.0);
bool res3 = simple_cmp(out_tensor.data<float>()[3], 2.0);
EXPECT_EQ(res0, true);
EXPECT_EQ(res1, true);
EXPECT_EQ(res2, true);
EXPECT_EQ(res3, true);
}
TEST(StandaloneExecutor, run_error) {
pir::IrContext* ctx = pir::IrContext::Instance();
pir::Program program((ctx));
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
pir::Builder builder = pir::Builder(ctx, program.block());
paddle::dialect::FullOp op1 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2, 2}, 1.0, phi::DataType::FLOAT32, phi::CPUPlace());
paddle::dialect::FullOp op2 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2, 2}, 1.0, phi::DataType::FLOAT64, phi::CPUPlace());
auto add_op =
builder.Build<paddle::dialect::AddOp>(op1->result(0), op2->result(0));
std::string out_name = "add_out";
builder.Build<pir::ShadowOutputOp>(add_op->result(0), out_name);
auto kernel_program = pir::PdOpLowerToKernelPass(&program);
for (auto op : kernel_program->block()->ops()) {
op->erase_attribute("origin_id");
}
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
try {
test_core.Run({});
} catch (std::exception& e) {
bool is_catch =
std::string(e.what()).find("InvalidArgumentError") != std::string::npos;
EXPECT_EQ(is_catch, true);
}
}
TEST(StandaloneExecutor, run_feed_tensor) {
pir::IrContext* ctx = pir::IrContext::Instance();
pir::Program program(ctx);
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
pir::Builder builder = pir::Builder(ctx, program.block());
pir::OpInfo feed_op_info =
ctx->GetRegisteredOpInfo(paddle::dialect::FeedOp::name());
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
phi::DDim dims = {1};
phi::DataLayout data_layout = phi::DataLayout::NCHW;
phi::LegacyLoD lod = {{0}};
size_t offset = 0;
pir::Type dense_tensor_dtype = paddle::dialect::DenseTensorType::get(
ctx, fp32_dtype, dims, data_layout, lod, offset);
pir::AttributeMap attr_map1;
attr_map1.insert(std::pair<std::string, pir::Attribute>(
"name", pir::StrAttribute::get(ctx, "x")));
attr_map1.insert(std::pair<std::string, pir::Attribute>(
"col", pir::Int32Attribute::get(ctx, 0)));
pir::Operation* feed_op1 =
pir::Operation::Create({}, attr_map1, {dense_tensor_dtype}, feed_op_info);
program.block()->push_back(feed_op1);
pir::AttributeMap attr_map2;
attr_map2.insert(std::pair<std::string, pir::Attribute>(
"name", pir::StrAttribute::get(ctx, "y")));
attr_map2.insert(std::pair<std::string, pir::Attribute>(
"col", pir::Int32Attribute::get(ctx, 0)));
pir::Operation* feed_op2 =
pir::Operation::Create({}, attr_map2, {dense_tensor_dtype}, feed_op_info);
program.block()->push_back(feed_op2);
auto add_op = builder.Build<paddle::dialect::AddOp>(feed_op1->result(0),
feed_op2->result(0));
std::string out_name = "add_out";
builder.Build<pir::ShadowOutputOp>(add_op->result(0), out_name);
auto kernel_program = pir::PdOpLowerToKernelPass(&program);
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
phi::DenseTensorMeta meta(
phi::DataType::FLOAT32, dims, data_layout, lod, offset);
phi::DeviceContext* dev_ctx =
phi::DeviceContextPool::Instance().Get(phi::CPUPlace());
phi::DenseTensor tensor_x;
tensor_x.set_meta(meta);
dev_ctx->Alloc(&tensor_x, phi::DataType::FLOAT32);
float* tensor_x_data = tensor_x.data<float>();
*tensor_x_data = 1.0;
phi::DenseTensor tensor_y;
tensor_y.set_meta(meta);
dev_ctx->Alloc(&tensor_y, phi::DataType::FLOAT32);
float* tensor_y_data = tensor_y.data<float>();
*tensor_y_data = 2.0;
test_core.Run({"x", "y"}, {tensor_x, tensor_y});
auto out_tensor =
test_core.local_scope() == nullptr
? scope.FindVar(out_name)->Get<phi::DenseTensor>()
: test_core.local_scope()->FindVar(out_name)->Get<phi::DenseTensor>();
bool res0 = simple_cmp(out_tensor.data<float>()[0], 3.0);
EXPECT_EQ(res0, true);
}
TEST(StandaloneExecutor, run_inplace_sqrt) {
pir::IrContext* ctx = pir::IrContext::Instance();
pir::Program program((ctx));
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
pir::Builder builder = pir::Builder(ctx, program.block());
paddle::dialect::FullOp full = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2, 2}, 4.0, phi::DataType::FLOAT32, phi::CPUPlace());
builder.Build<paddle::dialect::Sqrt_Op>(full->result(0));
std::string out_name = "full_out";
builder.Build<pir::ShadowOutputOp>(full->result(0), out_name);
auto kernel_program = pir::PdOpLowerToKernelPass(&program);
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
test_core.Run({});
auto out_tensor =
test_core.local_scope() == nullptr
? scope.FindVar(out_name)->Get<phi::DenseTensor>()
: test_core.local_scope()->FindVar(out_name)->Get<phi::DenseTensor>();
bool res0 = simple_cmp(out_tensor.data<float>()[0], 2.0);
bool res1 = simple_cmp(out_tensor.data<float>()[1], 2.0);
bool res2 = simple_cmp(out_tensor.data<float>()[2], 2.0);
bool res3 = simple_cmp(out_tensor.data<float>()[3], 2.0);
EXPECT_EQ(scope.kids().size(), 1u);
EXPECT_EQ(scope.kids().front()->Size(), 2u);
EXPECT_EQ(res0, true);
EXPECT_EQ(res1, true);
EXPECT_EQ(res2, true);
EXPECT_EQ(res3, true);
}
TEST(StandaloneExecutor, if_op) {
pir::IrContext* ctx = pir::IrContext::Instance();
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
ctx->GetOrRegisterDialect<pir::ControlFlowDialect>();
pir::Program program(ctx);
pir::Block* block = program.block();
pir::Builder builder(ctx, block);
auto full_op = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{1}, true, phi::DataType::BOOL);
auto if_op = builder.Build<paddle::dialect::IfOp>(
full_op.out(), std::vector<pir::Type>{full_op.result(0).type()});
auto& true_block = if_op.true_block();
builder.SetInsertionPointToStart(&true_block);
auto full_op_1 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{2}, true, phi::DataType::BOOL);
builder.Build<pir::YieldOp>(std::vector<pir::Value>{full_op_1.out()});
auto& false_block = if_op.false_block();
builder.SetInsertionPointToStart(&false_block);
auto full_op_2 = builder.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{3}, true, phi::DataType::BOOL);
builder.Build<pir::YieldOp>(std::vector<pir::Value>{full_op_2.out()});
std::string out_name = "if_out";
builder.SetInsertionPointToBlockEnd(block);
builder.Build<pir::ShadowOutputOp>(if_op->result(0), out_name);
auto kernel_program = pir::PdOpLowerToKernelPass(&program);
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
test_core.Run({});
auto out_tensor =
test_core.local_scope() == nullptr
? scope.FindVar(out_name)->Get<phi::DenseTensor>()
: test_core.local_scope()->FindVar(out_name)->Get<phi::DenseTensor>();
bool res0 = out_tensor.data<bool>()[0] == true;
bool res1 = out_tensor.data<bool>()[1] == true;
EXPECT_EQ(res0, true);
EXPECT_EQ(res1, true);
}
using namespace paddle::dialect; // NOLINT
TEST(StandaloneExecutor, while_op) {
pir::IrContext* ctx = pir::IrContext::Instance();
ctx->GetOrRegisterDialect<OperatorDialect>();
ctx->GetOrRegisterDialect<pir::ControlFlowDialect>();
pir::Program program(ctx);
pir::Block* block = program.block();
pir::Builder builder(ctx, block);
auto i = builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{1}, 1, phi::DataType::INT32)
.out();
auto ten = builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>{1}, 10, phi::DataType::INT32)
.out();
// compute condition value: i <= ten
auto cond_value = builder.Build<LessEqualOp>(i, ten).out();
auto while_op =
builder.Build<WhileOp>(cond_value, std::vector<pir::Value>{i, ten});
// { i = i + 1}
pir::Block& body_block = while_op.body();
auto body_i_argument = body_block.arg(0);
auto body_ten_argument = body_block.arg(1);
builder.SetInsertionPointToStart(&body_block);
auto one =
builder.Build<FullOp>(std::vector<int64_t>{1}, 1, phi::DataType::INT32)
.out();
auto new_i = builder.Build<AddOp>(body_i_argument, one).out();
// compute new condition value: new_i <= new_ten
auto new_cond_value =
builder.Build<LessEqualOp>(new_i, body_ten_argument).out();
builder.Build<pir::YieldOp>(
std::vector<pir::Value>{new_cond_value, new_i, body_ten_argument});
builder.SetInsertionPointAfter(while_op);
std::string out_name = "while_out";
builder.Build<pir::ShadowOutputOp>(while_op->result(0), out_name);
auto kernel_program = PdOpLowerToKernelPass(&program);
auto place = phi::CPUPlace();
Scope scope;
InterpreterCore test_core(place, {}, kernel_program->block(), &scope);
test_core.SetSkipGcVars({out_name});
test_core.Run({});
auto out_tensor =
test_core.local_scope() == nullptr
? scope.FindVar(out_name)->Get<phi::DenseTensor>()
: test_core.local_scope()->FindVar(out_name)->Get<phi::DenseTensor>();
bool res0 = out_tensor.data<int>()[0] == 11;
EXPECT_EQ(res0, true);
}
} // namespace framework
} // namespace paddle
@@ -0,0 +1,264 @@
// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/framework/new_executor/standalone_executor.h"
#include <gtest/gtest.h>
#include <chrono>
#include <iostream>
#include <memory>
#include <string>
#include "paddle/fluid/framework/new_executor/interpreter/plan.h"
#include "paddle/phi/core/kernel_registry.h"
USE_OP_ITSELF(fill_constant);
USE_OP_ITSELF(uniform_random);
USE_OP_ITSELF(lookup_table);
USE_OP_ITSELF(transpose2);
USE_OP_ITSELF(reshape2);
USE_OP_ITSELF(split);
USE_OP_ITSELF(slice);
USE_OP_ITSELF(concat);
USE_OP_ITSELF(matmul);
USE_OP_ITSELF(elementwise_add);
USE_OP_ITSELF(sigmoid);
USE_OP_ITSELF(tanh);
USE_OP_ITSELF(elementwise_mul);
USE_OP_ITSELF(softmax_with_cross_entropy);
USE_OP_ITSELF(reduce_mean);
USE_OP_ITSELF(reduce_sum);
USE_OP_ITSELF(reduce_sum_grad);
USE_OP_ITSELF(reduce_mean_grad);
USE_OP_ITSELF(reshape2_grad);
USE_OP_ITSELF(softmax_with_cross_entropy_grad);
USE_OP_ITSELF(elementwise_add_grad);
USE_OP_ITSELF(matmul_grad);
USE_OP_ITSELF(square);
USE_OP_ITSELF(transpose2_grad);
USE_OP_ITSELF(concat_grad);
USE_OP_ITSELF(elementwise_mul_grad);
USE_OP_ITSELF(sigmoid_grad);
USE_OP_ITSELF(tanh_grad);
USE_OP_ITSELF(sum);
USE_OP_ITSELF(slice_grad);
USE_OP_ITSELF(lookup_table_grad);
USE_OP_ITSELF(sqrt);
USE_OP_ITSELF(elementwise_max);
USE_OP_ITSELF(elementwise_div);
USE_OP_ITSELF(sgd);
USE_OP_ITSELF(squared_l2_norm);
USE_OP_ITSELF(memcpy_h2d);
USE_OP_ITSELF(memcpy_d2h);
PD_DECLARE_KERNEL(full, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(uniform_raw, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(uniform, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(transpose, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(reshape, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(split, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(concat, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(concat_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(matmul, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(add_raw, KPS, ALL_LAYOUT);
PD_DECLARE_KERNEL(add, KPS, ALL_LAYOUT);
PD_DECLARE_KERNEL(multiply, KPS, ALL_LAYOUT);
PD_DECLARE_KERNEL(multiply_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(divide, KPS, ALL_LAYOUT);
#ifdef PADDLE_WITH_XPU_KP
PD_DECLARE_KERNEL(max_raw, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(maximum, GPU, ALL_LAYOUT);
#else
PD_DECLARE_KERNEL(max_raw, KPS, ALL_LAYOUT);
PD_DECLARE_KERNEL(maximum, KPS, ALL_LAYOUT);
#endif
PD_DECLARE_KERNEL(mean, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(mean_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sigmoid, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sigmoid_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(squared_l2_norm, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(reshape_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(add_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(matmul_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(transpose_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sum, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sum_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sgd, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(slice, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(slice_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(cross_entropy_with_softmax, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(cross_entropy_with_softmax_grad, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(sqrt, GPU, ALL_LAYOUT);
PD_DECLARE_KERNEL(add_n, GPU, ALL_LAYOUT);
namespace paddle {
namespace framework {
using Job = interpreter::Job;
using Plan = interpreter::Plan;
ProgramDesc load_from_file(const std::string& file_name) {
std::ifstream fin(file_name, std::ios::in | std::ios::binary);
fin.seekg(0, std::ios::end);
std::string buffer(fin.tellg(), ' ');
fin.seekg(0, std::ios::beg);
fin.read(&buffer[0], buffer.size()); // NOLINT
fin.close();
ProgramDesc program_desc(buffer);
return program_desc;
}
ProgramDesc GetLmMainProgram() {
ProgramDesc main_prog = load_from_file("lm_main_program");
auto& global_block = main_prog.Block(0);
int64_t batch_size = 20;
const auto allOps = global_block.AllOps();
auto& op1 = allOps[1];
auto shape1 = PADDLE_GET_CONST(std::vector<int64_t>, op1->GetAttr("shape"));
shape1[0] = batch_size * 20;
op1->SetAttr("shape", shape1);
auto& op2 = allOps[2];
auto shape2 = PADDLE_GET_CONST(std::vector<int64_t>, op2->GetAttr("shape"));
shape2[0] = batch_size;
op2->SetAttr("shape", shape2);
auto& op3 = allOps[3];
auto shape3 = PADDLE_GET_CONST(std::vector<int64_t>, op3->GetAttr("shape"));
shape3[0] = batch_size;
op3->SetAttr("shape", shape3);
return main_prog;
}
TEST(InterpreterCore, skip_gc_vars) {
auto place = phi::GPUPlace(0);
ProgramDesc startup_prog = load_from_file("lm_startup_program");
ProgramDesc main_prog = GetLmMainProgram();
Scope scope;
std::shared_ptr<InterpreterCore> startup_core =
std::make_shared<InterpreterCore>(
place, startup_prog.Block(0), &scope, interpreter::ExecutionConfig());
startup_core->Run({}, {});
std::set<std::string> skip_gc_vars = {"uniform_0.tmp_0",
"transpose_0.tmp_0",
"embedding_0.tmp_0",
"slice_0.tmp_0",
"split_1.tmp_2"};
std::set<std::string> gc_vars = {"uniform_1.tmp_0",
"matmul_0.tmp_0",
"split_0.tmp_0",
"elementwise_add_0.tmp_0",
"tmp_0"};
interpreter::ExecutionConfig execution_config;
execution_config.skip_gc_vars = skip_gc_vars;
std::shared_ptr<InterpreterCore> main_core =
std::make_shared<InterpreterCore>(
place, main_prog.Block(0), &scope, execution_config);
auto check_gc_result =
[](Scope& scope, std::set<std::string>& vars, bool is_skip_gc) {
// the first local scope is created in startup_core
// the second local scope is created in main_core
ASSERT_EQ(scope.kids().size(), 2UL);
auto* local_scope = scope.kids().back();
for (const std::string& var_name : vars) {
ASSERT_EQ(local_scope->FindVar(var_name)
->GetMutable<phi::DenseTensor>()
->IsInitialized(),
is_skip_gc);
}
};
main_core->Run({}, {});
check_gc_result(scope, skip_gc_vars, true);
check_gc_result(scope, gc_vars, false);
main_core->Run({}, {});
check_gc_result(scope, skip_gc_vars, true);
check_gc_result(scope, gc_vars, false);
}
void TestShareWorkQueue(const ProgramDesc& prog,
const std::vector<std::string>& feed_names,
const std::vector<phi::DenseTensor>& feed_tensors,
const std::vector<std::string>& fetch_names,
const std::vector<float>& fetch_results) {
const phi::CPUPlace place = phi::CPUPlace();
Scope scope;
std::shared_ptr<InterpreterCore> core1 = std::make_shared<InterpreterCore>(
place, prog.Block(0), &scope, interpreter::ExecutionConfig());
std::shared_ptr<InterpreterCore> core2 = std::make_shared<InterpreterCore>(
place, prog.Block(0), &scope, interpreter::ExecutionConfig());
core2->ShareWorkQueueFrom(core1);
auto run_and_check = [&feed_names, &feed_tensors, &fetch_results](
std::shared_ptr<InterpreterCore> core) {
FetchList fetch_list = core->Run(feed_names, feed_tensors);
for (size_t i = 0; i < fetch_list.size(); ++i) {
const float* fetch_data =
PADDLE_GET_CONST(phi::DenseTensor, fetch_list[i]).data<float>();
ASSERT_FLOAT_EQ(*fetch_data, fetch_results.at(i));
}
};
run_and_check(core1);
run_and_check(core2);
run_and_check(core1);
run_and_check(core2);
}
TEST(InterpreterCore, workqueue_multiplexing) {
ProgramDesc program;
BlockDesc* main_block = program.MutableBlock(0);
VarDesc* var_a = main_block->Var("a");
VarDesc* var_b = main_block->Var("b");
VarDesc* var_c = main_block->Var("c");
var_a->SetType(proto::VarType::DENSE_TENSOR);
var_b->SetType(proto::VarType::DENSE_TENSOR);
var_c->SetType(proto::VarType::DENSE_TENSOR);
OpDesc* add = main_block->AppendOp();
add->SetType("elementwise_add");
add->SetInput("X", {"a"});
add->SetInput("Y", {"b"});
add->SetOutput("Out", {"c"});
std::array<float, 4> data_a = {0, 1, 2, 3};
std::array<float, 4> data_b = {0.0, 0.1, 0.2, 0.3};
phi::DDim dims = common::make_ddim({2, 2});
const phi::CPUPlace place = phi::CPUPlace();
phi::DenseTensor tensor_a = phi::DenseTensor();
phi::DenseTensor tensor_b = phi::DenseTensor();
std::copy_n(data_a.data(), 4, tensor_a.mutable_data<float>(dims, place));
std::copy_n(data_b.data(), 4, tensor_b.mutable_data<float>(dims, place));
TestShareWorkQueue(
program, {"a", "b"}, {tensor_a, tensor_b}, {"c"}, {0.0, 1.1, 2.2, 3.3});
}
} // namespace framework
} // namespace paddle