提交 628aa0df 编写于 作者: Z zhupengyang 提交者: GitHub

get precision from real tensor or tensor_array of base_scope in arena/framwork (#3092)

* get the precision from the real tensor or tensor_array of base_scope in arena/framwork

* register assign and assign_value to kAny
上级 899d8841
...@@ -123,6 +123,115 @@ void TestCase::PrepareInputsForInstruction() { ...@@ -123,6 +123,115 @@ void TestCase::PrepareInputsForInstruction() {
} }
} }
template <typename T>
bool TestCase::CheckTensorPrecision(const Tensor* a_tensor,
const Tensor* b_tensor,
float abs_error) {
CHECK(a_tensor);
CHECK(b_tensor);
CHECK(ShapeEquals(a_tensor->dims(), b_tensor->dims()));
CHECK(a_tensor->lod() == b_tensor->lod()) << "lod not match";
// The baseline should output in host devices.
CHECK(b_tensor->target() == TARGET(kHost) ||
b_tensor->target() == TARGET(kX86) ||
b_tensor->target() == TARGET(kARM));
const T* a_data{};
switch (a_tensor->target()) {
case TARGET(kX86):
case TARGET(kHost):
case TARGET(kARM):
a_data = static_cast<const T*>(a_tensor->raw_data());
break;
default:
// Before compare, need to copy data from `target` device to host.
LOG(FATAL) << "Not supported";
}
CHECK(a_data);
const T* b_data = static_cast<const T*>(b_tensor->raw_data());
bool success = true;
for (int i = 0; i < a_tensor->dims().production(); i++) {
EXPECT_NEAR(a_data[i], b_data[i], abs_error);
if (fabsf(a_data[i] - b_data[i]) > abs_error) {
success = false;
}
}
return success;
}
bool TestCase::CheckPrecision(const Tensor* a_tensor,
const Tensor* b_tensor,
float abs_error,
PrecisionType precision_type) {
PrecisionType precision_type_t = precision_type;
if (precision_type == PRECISION(kAny)) {
precision_type_t = b_tensor->precision();
}
CHECK(precision_type_t == b_tensor->precision())
<< "arg precision type and base tensor precision type are not matched! "
"arg precision type is: "
<< PrecisionToStr(precision_type) << ", base tensor precision type is: "
<< PrecisionToStr(b_tensor->precision());
CHECK(a_tensor->precision() == b_tensor->precision())
<< "real tensor precision type and base tensor precision type are not "
"matched! real tensor precision type is: "
<< PrecisionToStr(a_tensor->precision())
<< ", base tensor precision type is: "
<< PrecisionToStr(b_tensor->precision());
switch (precision_type_t) {
case PRECISION(kFloat):
return CheckTensorPrecision<float>(a_tensor, b_tensor, abs_error);
case PRECISION(kInt8):
return CheckTensorPrecision<int8_t>(a_tensor, b_tensor, abs_error);
case PRECISION(kInt32):
return CheckTensorPrecision<int32_t>(a_tensor, b_tensor, abs_error);
case PRECISION(kInt64):
return CheckTensorPrecision<int64_t>(a_tensor, b_tensor, abs_error);
case PRECISION(kBool):
return CheckTensorPrecision<bool>(a_tensor, b_tensor, abs_error);
default:
LOG(FATAL) << "not support type: " << PrecisionToStr(precision_type);
return false;
}
}
bool TestCase::CheckPrecision(const std::string& var_name,
float abs_error,
PrecisionType precision_type) {
bool success = true;
if (inst_scope_->FindVar(var_name)->IsType<Tensor>()) {
auto a_tensor = inst_scope_->FindTensor(var_name);
auto b_tensor = base_scope_->FindTensor(var_name);
success = success &&
CheckPrecision(a_tensor, b_tensor, abs_error, precision_type);
} else if (inst_scope_->FindVar(var_name)->IsType<std::vector<Tensor>>()) {
auto a_tensor_array =
inst_scope_->FindVar(var_name)->GetMutable<std::vector<Tensor>>();
auto b_tensor_array =
base_scope_->FindVar(var_name)->GetMutable<std::vector<Tensor>>();
CHECK_EQ(a_tensor_array->size(), b_tensor_array->size());
for (int i = 0; i < a_tensor_array->size(); i++) {
Tensor* a_tensor = &(a_tensor_array->at(i));
Tensor* b_tensor = &(b_tensor_array->at(i));
if (a_tensor->dims().size() == 0 && b_tensor->dims().size() == 0) {
continue;
}
success = success &&
CheckPrecision(a_tensor, b_tensor, abs_error, precision_type);
}
} else {
LOG(FATAL) << "unsupported var type";
}
return success;
}
TestCase::~TestCase() { TestCase::~TestCase() {
if (op_desc_->Type() == "subgraph") { if (op_desc_->Type() == "subgraph") {
// Release the subblock desc of Subgraph op // Release the subblock desc of Subgraph op
......
...@@ -66,19 +66,24 @@ class TestCase { ...@@ -66,19 +66,24 @@ class TestCase {
/// output. /// output.
virtual void RunBaseline(Scope* scope) = 0; virtual void RunBaseline(Scope* scope) = 0;
// checkout the precision of the two tensors. b_tensor is from the baseline // checkout the precision of the two tensors with type T. b_tensor is baseline
template <typename T> template <typename T>
bool CheckTensorPrecision(const Tensor* a_tensor, bool CheckTensorPrecision(const Tensor* a_tensor,
const Tensor* b_tensor, const Tensor* b_tensor,
float abs_error); float abs_error);
// checkout the precision of the two tensors. b_tensor is baseline
bool CheckPrecision(const Tensor* a_tensor,
const Tensor* b_tensor,
float abs_error,
PrecisionType precision_type);
/// Check the precision of the output variables. It will compare the same /// Check the precision of the output variables. It will compare the same
/// tensor /// tensor (or all tensors of the tensor_array) in two scopes, one of the
/// (or all tensors of tensor_array) in two scopes, one of the instruction /// instruction execution, and the other for the baseline.
/// execution, bool CheckPrecision(const std::string& var_name,
/// and the other for the baseline. float abs_error,
template <typename T> PrecisionType precision_type);
bool CheckPrecision(const std::string& var_name, float abs_error);
const cpp::OpDesc& op_desc() { return *op_desc_; } const cpp::OpDesc& op_desc() { return *op_desc_; }
...@@ -86,20 +91,6 @@ class TestCase { ...@@ -86,20 +91,6 @@ class TestCase {
// kernel registry. // kernel registry.
void CheckKernelConsistWithDefinition() {} void CheckKernelConsistWithDefinition() {}
// Get the real precision of the output for check precision. When the declare
// precision obtained from the kernel is any, we should set the precision of
// the output in test case.
bool GetPrecisonType(const std::string& var_name,
PrecisionType* precision_type) {
auto res = precision_type_map_.find(var_name);
if (res == precision_type_map_.end()) {
return false;
} else {
*precision_type = precision_type_map_.at(var_name);
return true;
}
}
Scope& scope() { return *scope_; } Scope& scope() { return *scope_; }
Scope* baseline_scope() { return base_scope_; } Scope* baseline_scope() { return base_scope_; }
...@@ -159,19 +150,6 @@ class TestCase { ...@@ -159,19 +150,6 @@ class TestCase {
// Prepare for the operator. // Prepare for the operator.
virtual void PrepareOpDesc(cpp::OpDesc* op_desc) = 0; virtual void PrepareOpDesc(cpp::OpDesc* op_desc) = 0;
// Set the real precision of the output for check precision. When the declare
// precision obtained from the kernel is any, we should set the precision of
// the output in test case.
void SetPrecisionType(const std::string& var_name,
const PrecisionType& precision_type) {
auto res = precision_type_map_.find(var_name);
if (res == precision_type_map_.end()) {
precision_type_map_.insert({var_name, precision_type});
} else {
precision_type_map_.at(var_name) = precision_type;
}
}
public: public:
const Instruction& instruction() { return *instruction_; } const Instruction& instruction() { return *instruction_; }
...@@ -215,7 +193,6 @@ class TestCase { ...@@ -215,7 +193,6 @@ class TestCase {
Scope* base_scope_{}; Scope* base_scope_{};
std::unique_ptr<cpp::OpDesc> op_desc_; std::unique_ptr<cpp::OpDesc> op_desc_;
std::unique_ptr<Instruction> instruction_; std::unique_ptr<Instruction> instruction_;
std::unordered_map<std::string, PrecisionType> precision_type_map_;
}; };
class Arena { class Arena {
...@@ -272,24 +249,7 @@ class Arena { ...@@ -272,24 +249,7 @@ class Arena {
const Type* type = const Type* type =
tester_->instruction().kernel()->GetOutputDeclType(arg_name); tester_->instruction().kernel()->GetOutputDeclType(arg_name);
auto precision_type = type->precision(); auto precision_type = type->precision();
if (precision_type == PRECISION(kAny)) { return tester_->CheckPrecision(var_name, abs_error_, precision_type);
CHECK(tester_->GetPrecisonType(var_name, &precision_type));
}
switch (precision_type) {
case PRECISION(kFloat):
return tester_->CheckPrecision<float>(var_name, abs_error_);
case PRECISION(kInt8):
return tester_->CheckPrecision<int8_t>(var_name, abs_error_);
case PRECISION(kInt32):
return tester_->CheckPrecision<int32_t>(var_name, abs_error_);
case PRECISION(kInt64):
return tester_->CheckPrecision<int64_t>(var_name, abs_error_);
case PRECISION(kBool):
return tester_->CheckPrecision<bool>(var_name, abs_error_);
default:
LOG(FATAL) << "not support type " << PrecisionToStr(type->precision());
return false;
}
} }
private: private:
...@@ -298,77 +258,6 @@ class Arena { ...@@ -298,77 +258,6 @@ class Arena {
float abs_error_; float abs_error_;
}; };
template <typename T>
bool TestCase::CheckTensorPrecision(const Tensor* a_tensor,
const Tensor* b_tensor,
float abs_error) {
CHECK(a_tensor);
CHECK(b_tensor);
CHECK(ShapeEquals(a_tensor->dims(), b_tensor->dims()));
CHECK(a_tensor->lod() == b_tensor->lod()) << "lod not match";
// The baseline should output in host devices.
CHECK(b_tensor->target() == TARGET(kHost) ||
b_tensor->target() == TARGET(kX86) ||
b_tensor->target() == TARGET(kARM));
const T* a_data{};
switch (a_tensor->target()) {
case TARGET(kX86):
case TARGET(kHost):
case TARGET(kARM):
a_data = static_cast<const T*>(a_tensor->raw_data());
break;
default:
// Before compare, need to copy data from `target` device to host.
LOG(FATAL) << "Not supported";
}
CHECK(a_data);
const T* b_data = static_cast<const T*>(b_tensor->raw_data());
bool success = true;
for (int i = 0; i < a_tensor->dims().production(); i++) {
EXPECT_NEAR(a_data[i], b_data[i], abs_error);
if (fabsf(a_data[i] - b_data[i]) > abs_error) {
success = false;
}
}
return success;
}
template <typename T>
bool TestCase::CheckPrecision(const std::string& var_name, float abs_error) {
bool success = true;
if (inst_scope_->FindVar(var_name)->IsType<Tensor>()) {
auto a_tensor = inst_scope_->FindTensor(var_name);
auto b_tensor = base_scope_->FindTensor(var_name);
success = success && CheckTensorPrecision<T>(a_tensor, b_tensor, abs_error);
} else if (inst_scope_->FindVar(var_name)->IsType<std::vector<Tensor>>()) {
auto a_tensor_array =
inst_scope_->FindVar(var_name)->GetMutable<std::vector<Tensor>>();
auto b_tensor_array =
base_scope_->FindVar(var_name)->GetMutable<std::vector<Tensor>>();
CHECK_EQ(a_tensor_array->size(), b_tensor_array->size());
for (int i = 0; i < a_tensor_array->size(); i++) {
Tensor* a_tensor = &(a_tensor_array->at(i));
Tensor* b_tensor = &(b_tensor_array->at(i));
if (a_tensor->dims().size() == 0 && b_tensor->dims().size() == 0) {
continue;
}
success =
success && CheckTensorPrecision<T>(a_tensor, b_tensor, abs_error);
}
} else {
LOG(FATAL) << "unsupported var type";
}
return success;
}
} // namespace arena } // namespace arena
} // namespace lite } // namespace lite
} // namespace paddle } // namespace paddle
...@@ -23,16 +23,9 @@ namespace lite { ...@@ -23,16 +23,9 @@ namespace lite {
namespace kernels { namespace kernels {
namespace arm { namespace arm {
void AssignCompute::PrepareForRun() {
// CHECK_OR_FALSE(param_t.Out);
}
void AssignCompute::Run() { void AssignCompute::Run() {
// LOG(INFO) << "into kernel compute run";
auto& param = Param<param_t>(); auto& param = Param<param_t>();
const lite::Tensor* input = param.X; param.Out->CopyDataFrom(*param.X);
lite::Tensor* output = param.Out;
output->CopyDataFrom(*input);
} }
} // namespace arm } // namespace arm
...@@ -41,7 +34,7 @@ void AssignCompute::Run() { ...@@ -41,7 +34,7 @@ void AssignCompute::Run() {
} // namespace paddle } // namespace paddle
REGISTER_LITE_KERNEL( REGISTER_LITE_KERNEL(
assign, kARM, kFloat, kNCHW, paddle::lite::kernels::arm::AssignCompute, def) assign, kARM, kAny, kNCHW, paddle::lite::kernels::arm::AssignCompute, def)
.BindInput("X", {LiteType::GetTensorTy(TARGET(kARM))}) .BindInput("X", {LiteType::GetTensorTy(TARGET(kARM), PRECISION(kAny))})
.BindOutput("Out", {LiteType::GetTensorTy(TARGET(kARM))}) .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kARM), PRECISION(kAny))})
.Finalize(); .Finalize();
...@@ -22,10 +22,10 @@ namespace lite { ...@@ -22,10 +22,10 @@ namespace lite {
namespace kernels { namespace kernels {
namespace arm { namespace arm {
class AssignCompute : public KernelLite<TARGET(kARM), PRECISION(kFloat)> { class AssignCompute : public KernelLite<TARGET(kARM), PRECISION(kAny)> {
public: public:
using param_t = operators::AssignParam; using param_t = operators::AssignParam;
void PrepareForRun() override;
void Run() override; void Run() override;
virtual ~AssignCompute() = default; virtual ~AssignCompute() = default;
......
...@@ -58,9 +58,9 @@ void AssignValueCompute::Run() { ...@@ -58,9 +58,9 @@ void AssignValueCompute::Run() {
REGISTER_LITE_KERNEL(assign_value, REGISTER_LITE_KERNEL(assign_value,
kARM, kARM,
kFloat, kAny,
kNCHW, kNCHW,
paddle::lite::kernels::arm::AssignValueCompute, paddle::lite::kernels::arm::AssignValueCompute,
def) def)
.BindOutput("Out", {LiteType::GetTensorTy(TARGET(kARM))}) .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kARM), PRECISION(kAny))})
.Finalize(); .Finalize();
...@@ -22,7 +22,7 @@ namespace lite { ...@@ -22,7 +22,7 @@ namespace lite {
namespace kernels { namespace kernels {
namespace arm { namespace arm {
class AssignValueCompute : public KernelLite<TARGET(kARM), PRECISION(kFloat)> { class AssignValueCompute : public KernelLite<TARGET(kARM), PRECISION(kAny)> {
public: public:
using param_t = operators::AssignValueParam; using param_t = operators::AssignValueParam;
......
...@@ -67,13 +67,14 @@ void TestAssign(const Place& place) { ...@@ -67,13 +67,14 @@ void TestAssign(const Place& place) {
} }
TEST(Assign, precision) { TEST(Assign, precision) {
#ifdef LITE_WITH_X86 Place place;
Place place(TARGET(kX86));
#endif
#ifdef LITE_WITH_ARM #ifdef LITE_WITH_ARM
Place place(TARGET(kARM)); place = {TARGET(kARM), PRECISION(kAny)};
TestAssign(place); #else
return;
#endif #endif
TestAssign(place);
} }
} // namespace lite } // namespace lite
......
...@@ -95,10 +95,12 @@ class AssignValueComputeTester : public arena::TestCase { ...@@ -95,10 +95,12 @@ class AssignValueComputeTester : public arena::TestCase {
}; };
TEST(AssignValue, precision) { TEST(AssignValue, precision) {
LOG(INFO) << "test argmax op"; Place place;
#ifdef LITE_WITH_ARM #ifdef LITE_WITH_ARM
LOG(INFO) << "test argmax arm"; place = {TARGET(kARM), PRECISION(kAny)};
Place place(TARGET(kARM)); #else
return;
#endif
for (int dtype : {2, 5}) { for (int dtype : {2, 5}) {
for (int n : {1}) { for (int n : {1}) {
...@@ -114,7 +116,6 @@ TEST(AssignValue, precision) { ...@@ -114,7 +116,6 @@ TEST(AssignValue, precision) {
} }
} }
} }
#endif
} }
} // namespace lite } // namespace lite
......
...@@ -119,35 +119,6 @@ class CastComputeTester : public arena::TestCase { ...@@ -119,35 +119,6 @@ class CastComputeTester : public arena::TestCase {
LOG(FATAL) << "unsupported data type: " << in_dtype_; LOG(FATAL) << "unsupported data type: " << in_dtype_;
break; break;
} }
PrecisionType out_ptype;
switch (out_dtype_) {
case 0:
out_ptype = PRECISION(kBool);
break;
case 21:
out_ptype = PRECISION(kInt8);
break;
case 1:
out_ptype = PRECISION(kInt16);
break;
case 2:
out_ptype = PRECISION(kInt32);
break;
case 3:
out_ptype = PRECISION(kInt64);
break;
case 4:
out_ptype = PRECISION(kFP16);
break;
case 5:
out_ptype = PRECISION(kFloat);
break;
default:
LOG(FATAL) << "unsupported data type: " << out_dtype_;
break;
}
SetPrecisionType(out_, out_ptype);
} }
}; };
......
...@@ -86,8 +86,6 @@ class FillConstantBatchSizeLikeComputeTester : public arena::TestCase { ...@@ -86,8 +86,6 @@ class FillConstantBatchSizeLikeComputeTester : public arena::TestCase {
std::vector<float> din(in_dims_.production()); std::vector<float> din(in_dims_.production());
fill_data_rand(din.data(), -1.f, 1.f, in_dims_.production()); fill_data_rand(din.data(), -1.f, 1.f, in_dims_.production());
SetCommonTensor(input_, in_dims_, din.data(), in_lod_); SetCommonTensor(input_, in_dims_, din.data(), in_lod_);
SetPrecisionType(out_, PRECISION(kFloat));
} }
}; };
......
...@@ -109,7 +109,6 @@ class FillConstantComputeTester : public arena::TestCase { ...@@ -109,7 +109,6 @@ class FillConstantComputeTester : public arena::TestCase {
SetCommonTensor(shape_tensor_list_[i], DDim({1}), dshape_tensor.data()); SetCommonTensor(shape_tensor_list_[i], DDim({1}), dshape_tensor.data());
} }
} }
SetPrecisionType(out_, PRECISION(kFloat));
} }
}; };
......
...@@ -68,8 +68,6 @@ class ReadFromArrayComputeTester : public arena::TestCase { ...@@ -68,8 +68,6 @@ class ReadFromArrayComputeTester : public arena::TestCase {
std::vector<int64_t> didn(1); std::vector<int64_t> didn(1);
didn[0] = id_; didn[0] = id_;
SetCommonTensor(idn_, DDim{{1}}, didn.data()); SetCommonTensor(idn_, DDim{{1}}, didn.data());
SetPrecisionType(out_, PRECISION(kFloat));
} }
}; };
......
...@@ -107,7 +107,6 @@ class UnsqueezeComputeTester : public arena::TestCase { ...@@ -107,7 +107,6 @@ class UnsqueezeComputeTester : public arena::TestCase {
} }
void PrepareData() override { void PrepareData() override {
SetPrecisionType(out_, PRECISION(kFloat));
std::vector<float> in_data(dims_.production()); std::vector<float> in_data(dims_.production());
for (int i = 0; i < dims_.production(); ++i) { for (int i = 0; i < dims_.production(); ++i) {
in_data[i] = i; in_data[i] = i;
...@@ -214,7 +213,6 @@ class Unsqueeze2ComputeTester : public arena::TestCase { ...@@ -214,7 +213,6 @@ class Unsqueeze2ComputeTester : public arena::TestCase {
} }
void PrepareData() override { void PrepareData() override {
SetPrecisionType(out_, PRECISION(kFloat));
std::vector<float> in_data(dims_.production()); std::vector<float> in_data(dims_.production());
for (int i = 0; i < dims_.production(); ++i) { for (int i = 0; i < dims_.production(); ++i) {
in_data[i] = i; in_data[i] = i;
......
...@@ -66,8 +66,6 @@ class WriteToArrayComputeTester : public arena::TestCase { ...@@ -66,8 +66,6 @@ class WriteToArrayComputeTester : public arena::TestCase {
std::vector<int64_t> didn(1); std::vector<int64_t> didn(1);
didn[0] = id_; didn[0] = id_;
SetCommonTensor(idn_, DDim{{1}}, didn.data()); SetCommonTensor(idn_, DDim{{1}}, didn.data());
SetPrecisionType(out_, PRECISION(kFloat));
} }
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册