Files
2026-07-13 12:40:42 +08:00

363 lines
13 KiB
C++

// 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 <sstream>
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/fluid/eager/api/all.h"
#include "paddle/fluid/eager/api/generated/eager_generated/backwards/scale_node.h"
#include "paddle/fluid/eager/autograd_meta.h"
#include "paddle/fluid/eager/grad_node_info.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/core/tensor_meta.h"
#include "test/cpp/eager/test_utils.h"
PD_DECLARE_KERNEL(full, CPU, ALL_LAYOUT);
namespace egr {
TEST(Forward, SingleNode) {
// Prepare Device Contexts
eager_test::InitEnv(phi::CPUPlace());
// Prepare Inputs
std::vector<paddle::Tensor> target_tensors;
phi::DDim ddim = common::make_ddim({4, 16, 16, 32});
// Create Target Tensor
paddle::Tensor t = eager_test::CreateTensorWithValue(ddim,
phi::CPUPlace(),
phi::DataType::FLOAT32,
phi::DataLayout::NCHW,
5.0 /*value*/,
false /*is_leaf*/);
target_tensors.emplace_back(std::move(t));
paddle::Tensor& tensor = target_tensors[0];
EagerUtils::autograd_meta(&tensor)->SetStopGradient(false);
// Run Forward
float scale = 2.0;
float bias = 3.0;
paddle::Tensor out = egr::scale(
tensor, scale, bias, true /*bias_after_scale*/, true /*trace_backward*/);
// Examine Forward Output
eager_test::CompareTensorWithValue<float>(out, 13.0);
// Examine GradNode
{
// 1. GradNode
AutogradMeta* meta = EagerUtils::autograd_meta(&out);
GradNodeBase* grad_node = meta->GradNode();
GradNodeScale* scale_node = dynamic_cast<GradNodeScale*>(grad_node);
CHECK_NOTNULL(scale_node);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta->OutRankInfo().second) is not 0"));
}
}
/*
inp
|
Node0
|
Node1
|
out
*/
TEST(Forward, LinearNodes) {
eager_test::InitEnv(phi::CPUPlace());
// Prepare Inputs
std::vector<paddle::Tensor> target_tensors;
phi::DDim ddim = common::make_ddim({4, 16, 16, 32});
// Create Target Tensor
paddle::Tensor t = eager_test::CreateTensorWithValue(ddim,
phi::CPUPlace(),
phi::DataType::FLOAT32,
phi::DataLayout::NCHW,
5.0 /*value*/,
false /*is_leaf*/);
target_tensors.emplace_back(std::move(t));
paddle::Tensor& tensor = target_tensors[0];
EagerUtils::autograd_meta(&tensor)->SetStopGradient(false);
// Run Forward Node 0
float scale0 = 2.0;
float bias0 = 3.0;
paddle::Tensor out0 = egr::scale(tensor,
scale0,
bias0,
true /*bias_after_scale*/,
true /*trace_backward*/);
// Run Forward Node 1
float scale1 = 5.0;
float bias1 = 10.0;
paddle::Tensor out1 = egr::scale(
out0, scale1, bias1, true /*bias_after_scale*/, true /*trace_backward*/);
// Examine Forward Output 0
eager_test::CompareTensorWithValue<float>(out0, 13.0);
// Examine Forward Output 1
eager_test::CompareTensorWithValue<float>(out1, 75.0);
// Examine GradNode
{
// 1. GradNode
// Node 0
AutogradMeta* meta0 = EagerUtils::autograd_meta(&out0);
GradNodeBase* grad_node0 = meta0->GradNode();
GradNodeScale* scale_node0 = dynamic_cast<GradNodeScale*>(grad_node0);
CHECK_NOTNULL(scale_node0);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta0->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta0->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta0->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta0->OutRankInfo().second) is not 0"));
// Node 1
AutogradMeta* meta1 = EagerUtils::autograd_meta(&out1);
GradNodeBase* grad_node1 = meta1->GradNode();
GradNodeScale* scale_node1 = dynamic_cast<GradNodeScale*>(grad_node1);
CHECK_NOTNULL(scale_node1);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta1->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta1->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta1->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta1->OutRankInfo().second) is not 0"));
// 2. TensorWrapper: No TensorWrapper for ScaleNode
// 3. NextEdges: Node 1 -> Node 0
const paddle::small_vector<std::vector<GradSlotMeta>,
egr::kSlotSmallVectorSize>& node1_metas =
grad_node1->OutputMeta();
const auto& node1_meta = node1_metas[0];
PADDLE_ENFORCE_EQ(
static_cast<int>(node1_meta[0].GetEdge().GetEdgeRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(node1_meta[0].GetEdge().GetEdgeRankInfo().first)"
"is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(node1_meta[0].GetEdge().GetEdgeRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(node1_meta[0].GetEdge().GetEdgeRankInfo().second)"
"is not 0"));
PADDLE_ENFORCE_EQ(node1_meta[0].GetEdge().GetGradNode(),
grad_node0,
common::errors::InvalidArgument(
"node1_meta[0].GetEdge().GetGradNode() "
"is not equal with grad_node0, "
"the value of grad_node0 is %d "
"and node1_meta[0].GetEdge().GetGradNode() is %d",
grad_node0,
node1_meta[0].GetEdge().GetGradNode()));
}
}
/*
inp
|
Node0
____|____
| |
Node1 Node2
| |
out1 out2
*/
TEST(Forward, BranchedNodes) {
eager_test::InitEnv(phi::CPUPlace());
// Prepare Inputs
std::vector<paddle::Tensor> target_tensors;
phi::DDim ddim = common::make_ddim({4, 16, 16, 32});
// Create Target Tensor
paddle::Tensor t = eager_test::CreateTensorWithValue(ddim,
phi::CPUPlace(),
phi::DataType::FLOAT32,
phi::DataLayout::NCHW,
5.0 /*value*/,
false /*is_leaf*/);
target_tensors.emplace_back(std::move(t));
paddle::Tensor& tensor = target_tensors[0];
EagerUtils::autograd_meta(&tensor)->SetStopGradient(false);
// Run Forward Node 0
float scale0 = 2.0;
float bias0 = 3.0;
paddle::Tensor out0 = egr::scale(tensor,
scale0,
bias0,
true /*bias_after_scale*/,
true /*trace_backward*/);
// Run Forward Node 1
float scale1 = 5.0;
float bias1 = 10.0;
paddle::Tensor out1 = egr::scale(
out0, scale1, bias1, true /*bias_after_scale*/, true /*trace_backward*/);
// Run Forward Node 2
float scale2 = 10.0;
float bias2 = 20.0;
paddle::Tensor out2 = egr::scale(
out0, scale2, bias2, true /*bias_after_scale*/, true /*trace_backward*/);
// Examine Forward Output 0
eager_test::CompareTensorWithValue<float>(out0, 13.0);
// Examine Forward Output 1
eager_test::CompareTensorWithValue<float>(out1, 75.0);
// Examine Forward Output 2
eager_test::CompareTensorWithValue<float>(out2, 150.0);
// Examine GradNode
{
// 1. GradNode
// Node 0
AutogradMeta* meta0 = EagerUtils::autograd_meta(&out0);
GradNodeBase* grad_node0 = meta0->GradNode();
GradNodeScale* scale_node0 = dynamic_cast<GradNodeScale*>(grad_node0);
CHECK_NOTNULL(scale_node0);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta0->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta0->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta0->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta0->OutRankInfo().second) is not 0"));
// Node 1
AutogradMeta* meta1 = EagerUtils::autograd_meta(&out1);
GradNodeBase* grad_node1 = meta1->GradNode();
GradNodeScale* scale_node1 = dynamic_cast<GradNodeScale*>(grad_node1);
CHECK_NOTNULL(scale_node1);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta1->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta1->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta1->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta1->OutRankInfo().second) is not 0"));
// Node 2
AutogradMeta* meta2 = EagerUtils::autograd_meta(&out2);
GradNodeBase* grad_node2 = meta2->GradNode();
GradNodeScale* scale_node2 = dynamic_cast<GradNodeScale*>(grad_node2);
CHECK_NOTNULL(scale_node2);
PADDLE_ENFORCE_EQ(
static_cast<int>(meta2->OutRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta2->OutRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(meta2->OutRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(meta2->OutRankInfo().second) is not 0"));
// 2. TensorWrapper: No TensorWrapper for ScaleNode
// 3. NextEdges
// Node 1 -> Node 0
const paddle::small_vector<std::vector<GradSlotMeta>, kSlotSmallVectorSize>&
node1_metas = grad_node1->OutputMeta();
const Edge& node1_edge = node1_metas[0][0].GetEdge();
PADDLE_ENFORCE_EQ(
static_cast<int>(node1_edge.GetEdgeRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(node1_edge.GetEdgeRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(node1_edge.GetEdgeRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(node1_edge.GetEdgeRankInfo().second) is not 0"));
PADDLE_ENFORCE_EQ(
node1_edge.GetGradNode(),
grad_node0,
common::errors::InvalidArgument(
"node1_edge.GetGradNode() is not equal with grad_node0"
"the value of node1_edge.GetGradNode() is %d and grad_node0 is %d",
node1_edge.GetGradNode(),
grad_node0));
// Node 2 -> Node 0
const paddle::small_vector<std::vector<egr::GradSlotMeta>,
egr::kSlotSmallVectorSize>& node2_metas =
grad_node2->OutputMeta();
const Edge& node2_edge = node2_metas[0][0].GetEdge();
PADDLE_ENFORCE_EQ(
static_cast<int>(node2_edge.GetEdgeRankInfo().first),
0,
common::errors::InvalidArgument(
"static_cast<int>(node2_edge.GetEdgeRankInfo().first) is not 0"));
PADDLE_ENFORCE_EQ(
static_cast<int>(node2_edge.GetEdgeRankInfo().second),
0,
common::errors::InvalidArgument(
"static_cast<int>(node2_edge.GetEdgeRankInfo().second) is not 0"));
PADDLE_ENFORCE_EQ(
node2_edge.GetGradNode(),
grad_node0,
common::errors::InvalidArgument(
"node2_edge.GetGradNode() is not equal with grad_node0"
"the value of node2_edge.GetGradNode() is %d and grad_node0 is %d",
node2_edge.GetGradNode(),
grad_node0));
}
}
} // namespace egr