chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
nv_test(
|
||||
test_elementwise_add_op_inplace
|
||||
SRCS test_elementwise_add_op_inplace.cc
|
||||
DEPS executor op_registry elementwise_add_op scope phi common)
|
||||
cc_test(
|
||||
test_elementwise_div_grad_grad
|
||||
SRCS test_elementwise_div_grad_grad.cc
|
||||
DEPS executor op_registry elementwise_div_op scope phi common)
|
||||
cc_test(
|
||||
test_elementwise_add_grad_grad
|
||||
SRCS test_elementwise_add_grad_grad.cc
|
||||
DEPS executor op_registry elementwise_add_op scope phi common)
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2019 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 "gtest/gtest.h"
|
||||
#include "paddle/common/ddim.h"
|
||||
#include "paddle/fluid/framework/op_registry.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
#include "test/cpp/fluid/elementwise/test_elementwise_op_grad_grad.h"
|
||||
|
||||
USE_OP_ITSELF(elementwise_add);
|
||||
PD_DECLARE_KERNEL(add_double_grad, CPU, ALL_LAYOUT);
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
PD_DECLARE_KERNEL(add_double_grad, GPU, ALL_LAYOUT);
|
||||
#endif
|
||||
|
||||
namespace paddle {
|
||||
namespace operators {
|
||||
|
||||
template <typename T>
|
||||
class TestElementwiseAddGradGradWithoutDDX
|
||||
: public TestElementwiseOpGradGrad<T> {
|
||||
public:
|
||||
TestElementwiseAddGradGradWithoutDDX(const phi::Place &place,
|
||||
const phi::DDim &dims)
|
||||
: TestElementwiseOpGradGrad<T>("elementwise_add_grad_grad",
|
||||
place,
|
||||
dims,
|
||||
{"Y", "DOut", "DDY"},
|
||||
{"DDOut"}) {}
|
||||
|
||||
using TestElementwiseOpGradGrad<T>::feed_datas_;
|
||||
using TestElementwiseOpGradGrad<T>::expected_outs_;
|
||||
using TestElementwiseOpGradGrad<T>::dims_;
|
||||
void ComputeExpectedOuts() override {
|
||||
size_t numel = static_cast<size_t>(common::product(dims_));
|
||||
std::vector<T> dy(numel);
|
||||
std::vector<T> ddout(numel);
|
||||
for (size_t i = 0; i < numel; ++i) {
|
||||
// ddOut = ddX + ddY = ddY if ddX empty
|
||||
ddout[i] = feed_datas_["DDY"][i];
|
||||
}
|
||||
expected_outs_["DDOut"] = ddout;
|
||||
}
|
||||
|
||||
std::unique_ptr<framework::OperatorBase> CreateTestOp() override {
|
||||
auto op = framework::OpRegistry::CreateOp(
|
||||
this->op_type_,
|
||||
{{"Y", {"Y"}}, {"DOut", {"DOut"}}, {"DDY", {"DDY"}}},
|
||||
{{"DDOut", {"DDOut"}}},
|
||||
{{"use_onednn", false}, {"axis", 0}});
|
||||
return op;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_elementwise_add_grad_grad_without_ddx, cpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::CPUPlace p;
|
||||
TestElementwiseAddGradGradWithoutDDX<float> test(p, dims);
|
||||
ASSERT_TRUE(test.Check());
|
||||
}
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
TEST(test_elementwise_add_grad_grad_without_ddx, gpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::GPUPlace p(0);
|
||||
TestElementwiseAddGradGradWithoutDDX<float> test(p, dims);
|
||||
ASSERT_TRUE(test.Check());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace operators
|
||||
} // namespace paddle
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2019 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 <random>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/fluid/framework/lod_tensor.h"
|
||||
#include "paddle/fluid/framework/op_registry.h"
|
||||
#include "paddle/fluid/framework/scope.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
#include "paddle/phi/core/platform/device_context.h"
|
||||
|
||||
USE_OP_ITSELF(elementwise_add);
|
||||
|
||||
PD_DECLARE_KERNEL(add, CPU, ALL_LAYOUT);
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
PD_DECLARE_KERNEL(add, KPS, ALL_LAYOUT);
|
||||
#endif
|
||||
|
||||
namespace paddle {
|
||||
namespace operators {
|
||||
|
||||
static void Memcpy(void *dst, const void *src, size_t n, bool copy_to_gpu) {
|
||||
if (copy_to_gpu) {
|
||||
#ifdef PADDLE_WITH_CUDA
|
||||
PADDLE_ENFORCE_GPU_SUCCESS(cudaMemcpy(dst, src, n, cudaMemcpyHostToDevice));
|
||||
#elif defined(PADDLE_WITH_HIP)
|
||||
PADDLE_ENFORCE_GPU_SUCCESS(hipMemcpy(dst, src, n, hipMemcpyHostToDevice));
|
||||
#else
|
||||
PADDLE_THROW(
|
||||
common::errors::InvalidArgument("Check your paddle version, current "
|
||||
"version is not compiled with cuda"));
|
||||
#endif
|
||||
} else {
|
||||
std::memcpy(dst, src, n);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool TestMain(const phi::Place &place, const phi::DDim &dims, bool inplace) {
|
||||
framework::Scope scope;
|
||||
auto *x = scope.Var("x")->GetMutable<phi::DenseTensor>();
|
||||
auto *y = scope.Var("y")->GetMutable<phi::DenseTensor>();
|
||||
auto *z = scope.Var("z")->GetMutable<phi::DenseTensor>();
|
||||
|
||||
x->Resize(dims);
|
||||
y->Resize(dims);
|
||||
z->Resize(dims);
|
||||
|
||||
size_t numel = static_cast<size_t>(common::product(dims));
|
||||
|
||||
auto x_ptr = x->mutable_data<T>(place);
|
||||
auto y_ptr = y->mutable_data<T>(place);
|
||||
auto z_ptr = z->mutable_data<T>(place);
|
||||
|
||||
std::uniform_real_distribution<T> dist(static_cast<T>(10.0),
|
||||
static_cast<T>(20.0));
|
||||
std::mt19937 engine;
|
||||
std::vector<T> x_data(numel), y_data(numel), z_data(numel);
|
||||
std::vector<T> sum_result(numel);
|
||||
|
||||
for (size_t i = 0; i < numel; ++i) {
|
||||
x_data[i] = dist(engine);
|
||||
y_data[i] = dist(engine);
|
||||
sum_result[i] = x_data[i] + y_data[i];
|
||||
z_data[i] = -1.0; // set some data that is not existed
|
||||
}
|
||||
|
||||
auto bytes = sizeof(T) * numel;
|
||||
bool is_gpu_place = phi::is_gpu_place(place);
|
||||
Memcpy(x_ptr, x_data.data(), bytes, is_gpu_place);
|
||||
Memcpy(y_ptr, y_data.data(), bytes, is_gpu_place);
|
||||
Memcpy(z_ptr, z_data.data(), bytes, is_gpu_place);
|
||||
|
||||
const char *out_name = inplace ? "x" : "z";
|
||||
auto op = framework::OpRegistry::CreateOp("elementwise_add",
|
||||
{{"X", {"x"}}, {"Y", {"y"}}},
|
||||
{{"Out", {out_name}}},
|
||||
{});
|
||||
op->Run(scope, place);
|
||||
phi::DeviceContextPool::Instance().Get(place)->Wait();
|
||||
|
||||
phi::DenseTensor cpu_out;
|
||||
auto &out_tensor = scope.FindVar(out_name)->Get<phi::DenseTensor>();
|
||||
PADDLE_ENFORCE_EQ(
|
||||
scope.kids().empty(),
|
||||
true,
|
||||
common::errors::InvalidArgument("The scope can not have the child scopes,"
|
||||
"please check your code."));
|
||||
if (inplace) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
&out_tensor,
|
||||
x,
|
||||
common::errors::InvalidArgument(
|
||||
"The output tensor should be same as input x in inplace mode,"
|
||||
" but now is not same."));
|
||||
} else {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
&out_tensor,
|
||||
z,
|
||||
common::errors::InvalidArgument(
|
||||
"The output tensor should be same as output z in normal mode,"
|
||||
" but now is not same."));
|
||||
}
|
||||
|
||||
if (is_gpu_place) {
|
||||
framework::TensorCopySync(out_tensor, phi::CPUPlace(), &cpu_out);
|
||||
} else {
|
||||
cpu_out = out_tensor;
|
||||
}
|
||||
|
||||
auto *out_ptr = cpu_out.data<T>();
|
||||
bool is_equal = std::equal(out_ptr, out_ptr + numel, sum_result.data());
|
||||
return is_equal;
|
||||
}
|
||||
|
||||
TEST(test_elementwise_add_inplace, cpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::CPUPlace p;
|
||||
ASSERT_TRUE(TestMain<float>(p, dims, true));
|
||||
}
|
||||
|
||||
TEST(test_elementwise_add_not_inplace, cpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::CPUPlace p;
|
||||
ASSERT_TRUE(TestMain<float>(p, dims, false));
|
||||
}
|
||||
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
TEST(test_elementwise_add_inplace, gpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::GPUPlace p(0);
|
||||
ASSERT_TRUE(TestMain<float>(p, dims, true));
|
||||
}
|
||||
|
||||
TEST(test_elementwise_add_not_inplace, gpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::GPUPlace p(0);
|
||||
ASSERT_TRUE(TestMain<float>(p, dims, false));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace operators
|
||||
} // namespace paddle
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) 2019 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 <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/fluid/framework/lod_tensor.h"
|
||||
#include "paddle/fluid/framework/op_registry.h"
|
||||
#include "paddle/fluid/framework/operator.h"
|
||||
#include "paddle/fluid/framework/scope.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
#include "paddle/phi/core/platform/device_context.h"
|
||||
#include "test/cpp/fluid/elementwise/test_elementwise_op_grad_grad.h"
|
||||
|
||||
USE_OP_ITSELF(elementwise_div);
|
||||
|
||||
PD_DECLARE_KERNEL(divide_double_grad, CPU, ALL_LAYOUT);
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
PD_DECLARE_KERNEL(divide_double_grad, GPU, ALL_LAYOUT);
|
||||
#endif
|
||||
|
||||
namespace paddle {
|
||||
namespace operators {
|
||||
|
||||
template <typename T>
|
||||
class TestElementwiseDivGradGradWithDout : public TestElementwiseOpGradGrad<T> {
|
||||
public:
|
||||
TestElementwiseDivGradGradWithDout(const phi::Place &place,
|
||||
const phi::DDim &dims)
|
||||
: TestElementwiseOpGradGrad<T>(
|
||||
"elementwise_div_grad_grad",
|
||||
place,
|
||||
dims,
|
||||
{"Y", "Out", "Out@GRAD", "DDX", "DDY", "DX"},
|
||||
{"Y@GRAD", "DDOut", "DOut"}) {}
|
||||
|
||||
using TestElementwiseOpGradGrad<T>::feed_datas_;
|
||||
using TestElementwiseOpGradGrad<T>::expected_outs_;
|
||||
using TestElementwiseOpGradGrad<T>::dims_;
|
||||
void ComputeExpectedOuts() override {
|
||||
size_t numel = static_cast<size_t>(common::product(dims_));
|
||||
std::vector<T> dy(numel);
|
||||
std::vector<T> ddout(numel);
|
||||
std::vector<T> dout(numel);
|
||||
for (size_t i = 0; i < numel; ++i) {
|
||||
// dY(Y@GRAD) = Out * dX * ddY / Y - dX * ddX / Y
|
||||
dy[i] = (feed_datas_["DX"][i] / feed_datas_["Y"][i]) *
|
||||
(feed_datas_["Out"][i] * feed_datas_["DDY"][i] -
|
||||
feed_datas_["DDX"][i]);
|
||||
// ddOut = ddX / Y - Out * ddY / Y = (ddX - Out * ddY) / Y
|
||||
ddout[i] = (feed_datas_["DDX"][i] -
|
||||
feed_datas_["Out"][i] * feed_datas_["DDY"][i]) /
|
||||
(feed_datas_["Y"][i]);
|
||||
// dOut = - DX * DDy
|
||||
dout[i] = -feed_datas_["DX"][i] * feed_datas_["DDY"][i];
|
||||
}
|
||||
expected_outs_["Y@GRAD"] = dy;
|
||||
expected_outs_["DDOut"] = ddout;
|
||||
expected_outs_["DOut"] = dout;
|
||||
}
|
||||
|
||||
std::unique_ptr<framework::OperatorBase> CreateTestOp() override {
|
||||
auto op = framework::OpRegistry::CreateOp(
|
||||
this->op_type_,
|
||||
{{"Y", {"Y"}},
|
||||
{"Out", {"Out"}},
|
||||
{"Out@GRAD", {"Out@GRAD"}},
|
||||
{"DDX", {"DDX"}},
|
||||
{"DDY", {"DDY"}},
|
||||
{"DX", {"DX"}}},
|
||||
{{"Y@GRAD", {"Y@GRAD"}}, {"DDOut", {"DDOut"}}, {"DOut", {"DOut"}}},
|
||||
{{"use_onednn", false}, {"axis", 0}});
|
||||
return op;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(test_elementwise_div_grad_grad, cpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::CPUPlace p;
|
||||
TestElementwiseDivGradGradWithDout<float> test(p, dims);
|
||||
ASSERT_TRUE(test.Check());
|
||||
}
|
||||
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
TEST(test_elementwise_div_grad_grad, gpu_place) {
|
||||
phi::DDim dims({32, 64});
|
||||
phi::GPUPlace p(0);
|
||||
TestElementwiseDivGradGradWithDout<float> test(p, dims);
|
||||
ASSERT_TRUE(test.Check());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace operators
|
||||
} // namespace paddle
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (c) 2019 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "paddle/fluid/framework/lod_tensor.h"
|
||||
#include "paddle/fluid/framework/op_registry.h"
|
||||
#include "paddle/fluid/framework/operator.h"
|
||||
#include "paddle/fluid/framework/scope.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/memory/memory.h"
|
||||
#include "paddle/phi/core/platform/device_context.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace operators {
|
||||
|
||||
// currently, this test class only support same dims
|
||||
template <typename T>
|
||||
class TestElementwiseOpGradGrad {
|
||||
public:
|
||||
TestElementwiseOpGradGrad(const std::string &op_type,
|
||||
const phi::Place &place,
|
||||
const phi::DDim &dims,
|
||||
const std::vector<std::string> &inputs,
|
||||
const std::vector<std::string> &outputs)
|
||||
: op_type_(op_type),
|
||||
place_(place),
|
||||
dims_(dims),
|
||||
inputs_(inputs),
|
||||
outputs_(outputs) {}
|
||||
|
||||
void InitVarInScope(std::string var_name) {
|
||||
in_out_tensors_[var_name] =
|
||||
scope_.Var(var_name)->template GetMutable<phi::DenseTensor>();
|
||||
in_out_tensors_[var_name]->Resize(dims_);
|
||||
in_out_tensors_[var_name]->template mutable_data<T>(place_);
|
||||
}
|
||||
|
||||
void InitFeedData(std::string var_name, size_t size) {
|
||||
// generate random data
|
||||
std::uniform_real_distribution<T> dist(static_cast<T>(10.0),
|
||||
static_cast<T>(20.0));
|
||||
std::mt19937 engine;
|
||||
std::vector<T> data(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
data[i] = dist(engine);
|
||||
}
|
||||
feed_datas_[var_name] = data;
|
||||
}
|
||||
|
||||
void Setup() {
|
||||
size_t numel = static_cast<size_t>(common::product(dims_));
|
||||
// init vars in scope and feed inputs
|
||||
for (auto in_name : inputs_) {
|
||||
InitVarInScope(in_name);
|
||||
InitFeedData(in_name, numel);
|
||||
}
|
||||
for (auto out_name : outputs_) {
|
||||
InitVarInScope(out_name);
|
||||
}
|
||||
|
||||
// feeding: copy data to tensor, out tensor don't need init
|
||||
auto bytes = sizeof(T) * numel;
|
||||
for (auto &in_name : inputs_) {
|
||||
auto dst = in_out_tensors_[in_name]->template data<T>();
|
||||
auto src = feed_datas_[in_name].data();
|
||||
auto src_place = phi::CPUPlace();
|
||||
if (phi::is_cpu_place(place_)) {
|
||||
auto dst_place = place_;
|
||||
memory::Copy(dst_place, dst, src_place, src, bytes);
|
||||
} else if (phi::is_gpu_place(place_)) {
|
||||
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
|
||||
auto dst_place = place_;
|
||||
memory::Copy(dst_place, dst, src_place, src, bytes, nullptr);
|
||||
#else
|
||||
PADDLE_THROW(common::errors::InvalidArgument(
|
||||
"Check your paddle version, current version is not compiled with "
|
||||
"cuda"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// calculate expected outputs
|
||||
ComputeExpectedOuts();
|
||||
}
|
||||
|
||||
bool Check() {
|
||||
Setup();
|
||||
auto op = CreateTestOp();
|
||||
op->Run(scope_, place_);
|
||||
phi::DeviceContextPool::Instance().Get(place_)->Wait();
|
||||
phi::DenseTensor cpu_out;
|
||||
PADDLE_ENFORCE_EQ(scope_.kids().empty(),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The scope can not have the child scopes,"
|
||||
"please check your code."));
|
||||
|
||||
// get outputs from scope and compare them with expected_outs
|
||||
bool all_equal = true;
|
||||
for (auto &out_name : outputs_) {
|
||||
auto &out_tensor =
|
||||
scope_.FindVar(out_name)->template Get<phi::DenseTensor>();
|
||||
if (phi::is_gpu_place(place_)) {
|
||||
framework::TensorCopySync(out_tensor, phi::CPUPlace(), &cpu_out);
|
||||
} else {
|
||||
cpu_out = out_tensor;
|
||||
}
|
||||
auto *out_ptr = cpu_out.data<T>();
|
||||
size_t numel = static_cast<size_t>(common::product(dims_));
|
||||
bool is_equal;
|
||||
if (op_type_ == "elementwise_div_grad_grad") {
|
||||
is_equal = std::equal(out_ptr,
|
||||
out_ptr + numel,
|
||||
expected_outs_[out_name].data(),
|
||||
[](const float &l, const float &r) {
|
||||
return fabs(l - r) < 0.0005;
|
||||
});
|
||||
} else {
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
is_equal = std::equal(
|
||||
out_ptr,
|
||||
out_ptr + numel,
|
||||
expected_outs_[out_name].data(),
|
||||
[](const float &l, const float &r) { return fabs(l - r) < 1e-8; });
|
||||
#else
|
||||
is_equal = std::equal(
|
||||
out_ptr, out_ptr + numel, expected_outs_[out_name].data());
|
||||
#endif
|
||||
}
|
||||
if (!is_equal) {
|
||||
all_equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return all_equal;
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<framework::OperatorBase> CreateTestOp() = 0;
|
||||
virtual void ComputeExpectedOuts() = 0;
|
||||
virtual ~TestElementwiseOpGradGrad() {}
|
||||
|
||||
protected:
|
||||
std::string op_type_;
|
||||
phi::Place place_;
|
||||
phi::DDim dims_;
|
||||
std::vector<std::string> inputs_;
|
||||
std::vector<std::string> outputs_;
|
||||
std::map<std::string, phi::DenseTensor *> in_out_tensors_;
|
||||
std::map<std::string, std::vector<T>> feed_datas_;
|
||||
std::map<std::string, std::vector<T>> expected_outs_;
|
||||
framework::Scope scope_;
|
||||
};
|
||||
|
||||
} // namespace operators
|
||||
} // namespace paddle
|
||||
Reference in New Issue
Block a user