chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user