Add no scale check for resize and upsample (#1484)

Description: Describe your changes.
Add no scale check for resize and upsample
Motivation and Context

Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.
This commit is contained in:
Yufeng Li 2019-07-24 22:29:52 -07:00 committed by GitHub
parent 258ff06e42
commit a8e3ff47fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 70 deletions

View file

@ -256,15 +256,15 @@ void upsampleBilinear(
auto output_width = static_cast<int64_t>(input_width * width_scale);
auto output_height = static_cast<int64_t>(input_height * height_scale);
size_t inx_buffer_size = 2 * sizeof(int64_t) * (output_height + output_width);
size_t idx_buffer_size = 2 * sizeof(int64_t) * (output_height + output_width);
size_t scale_buffer_size = 2 * sizeof(float_t) * (output_height + output_width);
auto inx_scale_data_buffer = alloc->Alloc(inx_buffer_size + scale_buffer_size);
BufferUniquePtr inx_scale_data_buffer_holder(inx_scale_data_buffer, BufferDeleter(alloc));
auto* inx_data = static_cast<int64_t*>(inx_scale_data_buffer_holder.get());
int64_t* input_width_mul_y1 = inx_data;
int64_t* input_width_mul_y2 = inx_data + output_height;
int64_t* in_x1 = inx_data + 2 * output_height;
int64_t* in_x2 = inx_data + 2 * output_height + output_width;
auto inx_scale_data_buffer = alloc->Alloc(idx_buffer_size + scale_buffer_size);
BufferUniquePtr idx_scale_data_buffer_holder(inx_scale_data_buffer, BufferDeleter(alloc));
auto* idx_data = static_cast<int64_t*>(idx_scale_data_buffer_holder.get());
int64_t* input_width_mul_y1 = idx_data;
int64_t* input_width_mul_y2 = idx_data + output_height;
int64_t* in_x1 = idx_data + 2 * output_height;
int64_t* in_x2 = idx_data + 2 * output_height + output_width;
auto* scale_data = reinterpret_cast<float*>(in_x2 + output_width);
float* dy1 = scale_data;
@ -331,12 +331,21 @@ Status Upsample<T>::BaseCompute(OpKernelContext* context, const std::vector<floa
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "Upsample: input tensor's dimension does not match the scales.");
}
bool no_scale = true;
std::vector<int64_t> Y_dims;
Y_dims.reserve( dims.size() );
for (std::size_t i = 0; i < dims.size(); i++) {
Y_dims.push_back(static_cast<int64_t>(scales[i] * dims[i]));
int64_t dim_y = static_cast<int64_t>(scales[i] * dims[i]);
if (no_scale && dim_y != dims[i]) no_scale = false;
Y_dims.push_back(dim_y);
}
Tensor* Y = context->Output(0, Y_dims);
if (no_scale) {
memcpy(Y->MutableDataRaw(), X->DataRaw(), Y->Size() * sizeof(T));
return Status::OK();
}
switch (mode_) {
case UpsampleMode::NN:
return UpsampleNearest<T>(X->template Data<T>(), Y->template MutableData<T>(), X->Shape(), Y->Shape(), scales);

View file

@ -27,7 +27,82 @@ TEST(ResizeOpTest, ResizeOpLineartDownSampleTest) {
test.Run();
}
TEST(ResizeOpTest, ResizeOpUpsampleNearestTest) {
TEST(ResizeOpTest, ResizeOpLineartUpSampleTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 2.0f, 4.0f};
test.AddAttribute("mode", "linear");
const int64_t N = 2, C = 1, H = 2, W = 2;
std::vector<float> X = {1.0f, 3.0f,
4.0f, 8.0f,
6.0f, 2.0f,
7.0f, 11.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
test.AddInput<float>("scales", {4}, scales);
std::vector<float> Y = {
1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f,
2.5f, 3.25f, 4.0f, 4.75f, 5.5f, 5.5f, 5.5f, 5.5f,
4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f,
4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f,
6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 2.0f, 2.0f, 2.0f,
6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f,
7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f,
7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f};
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run();
}
TEST(ResizeOpTest, ResizeOpLineartNoScaleTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 1.0f, 1.0f};
test.AddAttribute("mode", "linear");
const int64_t N = 2, C = 1, H = 2, W = 2;
std::vector<float> X = {1.0f, 3.0f,
4.0f, 8.0f,
6.0f, 2.0f,
7.0f, 11.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
test.AddInput<float>("scales", {4}, scales);
std::vector<float> Y = {1.0f, 3.0f,
4.0f, 8.0f,
6.0f, 2.0f,
7.0f, 11.0f};
test.AddOutput<float>("Y", {N, C, H, W}, Y);
test.Run();
}
TEST(ResizeOpTest, ResizeOpNearestDownSampleTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 0.6f, 0.6f};
test.AddAttribute("mode", "nearest");
const int64_t N = 1, C = 1, H = 2, W = 4;
std::vector<float> X = {
1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
test.AddInput<float>("scales", {4}, scales);
std::vector<float> Y = {1.0f, 3.0f};
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run();
}
TEST(ResizeOpTest, ResizeOpNearestUpSampleTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 2.0f, 3.0f};
@ -48,55 +123,21 @@ TEST(ResizeOpTest, ResizeOpUpsampleNearestTest) {
test.Run();
}
TEST(ResizeOpTest, ResizeOpNearestTest) {
TEST(UpsampleOpTest, ResizeOpNearestNoScaleTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 0.6f, 0.6f};
std::vector<float> scales{1.0f, 1.0f, 1.0f, 1.0f};
test.AddAttribute("mode", "nearest");
const int64_t N = 1, C = 1, H = 2, W = 4;
std::vector<float> X = {
1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f};
const int64_t N = 1, C = 1, H = 2, W = 2;
std::vector<float> X = {1.0f, 2.0f, 3.0f, 4.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
test.AddInput<float>("scales", {4}, scales);
std::vector<float> Y = {1.0f, 3.0f};
std::vector<float> Y = {1.0f, 2.0f, 3.0f, 4.0f};
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run();
}
TEST(ResizeOpTest, ResizeOpBilinearTest) {
OpTester test("Resize", 10);
std::vector<float> scales{1.0f, 1.0f, 0.5f, 0.5f};
test.AddAttribute("mode", "linear");
const int64_t N = 2, C = 1, H = 4, W = 8;
std::vector<float> X = {
1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f,
2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.0f, 4.0f, 4.0f,
3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f,
3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f,
3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f,
5.0f, 5.5f, 6.0f, 6.5f, 7.0f, 7.0f, 7.0f, 7.0f,
7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.0f, 9.0f, 9.0f,
7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.0f, 9.0f, 9.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
test.AddInput<float>("scales", {4}, scales);
std::vector<float> Y = {
1.0f, 2.0f, 3.0f, 3.0f,
3.0f, 4.0f, 5.0f, 5.0f,
3.0f, 4.0f, 5.0f, 5.0f,
7.0f, 8.0f, 9.0f, 9.0f};
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.AddOutput<float>("Y", {N, C, H, W}, Y);
test.Run();
}

View file

@ -70,7 +70,7 @@ TEST(UpsampleOpTest, UpsampleOpNearestTest_int32) {
7, 7, 7, 9, 9, 9};
test.AddOutput<int32_t>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
}
TEST(UpsampleOpTest, UpsampleOpNearestTest_uint8) {
@ -170,10 +170,9 @@ TEST(UpsampleOpTest, UpsampleOpNearest222XTest) {
3.0f, 3.0f, 5.0f, 5.0f,
3.0f, 3.0f, 5.0f, 5.0f,
7.0f, 7.0f, 9.0f, 9.0f,
7.0f, 7.0f, 9.0f, 9.0f
};
7.0f, 7.0f, 9.0f, 9.0f};
test.AddOutput<float>("Y", {N*2, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.AddOutput<float>("Y", {N * 2, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run();
}
@ -208,6 +207,32 @@ TEST(UpsampleOpTest, UpsampleOpNearest15XTest) {
test.Run();
}
TEST(UpsampleOpTest, UpsampleOpNearestTest_NoScale) {
OpTester test("Upsample");
std::vector<float> scales{1.0f, 1.0f, 1.0f, 1.0f};
test.AddAttribute("mode", "nearest");
test.AddAttribute("scales", scales);
const int64_t N = 1, C = 2, H = 2, W = 2;
std::vector<float> X = {1.0f, 3.0f,
3.0f, 5.0f,
3.0f, 5.0f,
7.0f, 9.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
std::vector<float> Y = {1.0f, 3.0f,
3.0f, 5.0f,
3.0f, 5.0f,
7.0f, 9.0f};
test.AddOutput<float>("Y", {N, C, H, W}, Y);
test.Run();
}
TEST(UpsampleOpTest, UpsampleOpNearest2XTest_int32) {
OpTester test("Upsample");
@ -236,7 +261,7 @@ TEST(UpsampleOpTest, UpsampleOpNearest2XTest_int32) {
7, 7, 9, 9};
test.AddOutput<int32_t>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
}
TEST(UpsampleOpTest, UpsampleOpBilinearTest) {
@ -270,34 +295,29 @@ TEST(UpsampleOpTest, UpsampleOpBilinearTest) {
test.Run();
}
TEST(UpsampleOpTest, UpsampleOpBilinearTest2) {
TEST(UpsampleOpTest, UpsampleOpBilinearTest_NoScale) {
OpTester test("Upsample");
std::vector<float> scales{1.0f, 1.0f, 2.0f, 4.0f};
std::vector<float> scales{1.0f, 1.0f, 1.0f, 1.0f};
test.AddAttribute("mode", "linear");
test.AddAttribute("scales", scales);
const int64_t N = 2, C = 1, H = 2, W = 2;
std::vector<float> X = {1.0f, 3.0f,
4.0f, 8.0f,
3.0f, 5.0f,
6.0f, 2.0f,
7.0f, 11.0f};
3.0f, 5.0f,
7.0f, 9.0f};
test.AddInput<float>("X", {N, C, H, W}, X);
std::vector<float> Y = {
1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f,
2.5f, 3.25f, 4.0f, 4.75f, 5.5f, 5.5f, 5.5f, 5.5f,
4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f,
4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f,
std::vector<float> Y = {1.0f, 3.0f,
3.0f, 5.0f,
6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 2.0f, 2.0f, 2.0f,
6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f,
7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f,
7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f};
3.0f, 5.0f,
7.0f, 9.0f};
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.AddOutput<float>("Y", {N, C, H, W}, Y);
test.Run();
}