mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-11 17:48:34 +00:00
Upsample support NHWC (#10824)
This patch implement bilinear interpolation for Upsample/Resize 4-D input with the outermost and innermost scale (usually channel of NHWC) as 1. It is parallelized with output_height * output_width instead of one dimension only. Besides, I also revert the HandleResize back to the original implementation for TransposeOptimizerTests.TestResize* tests. Finally, I add microbenchmark BM_NhwcUpsampleBilinear.
This commit is contained in:
parent
269be2fe63
commit
749c0ddd1e
8 changed files with 1113 additions and 346 deletions
|
|
@ -873,6 +873,7 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP)
|
|||
${BENCHMARK_DIR}/main.cc
|
||||
${BENCHMARK_DIR}/modeltest.cc
|
||||
${BENCHMARK_DIR}/pooling.cc
|
||||
${BENCHMARK_DIR}/resize.cc
|
||||
${BENCHMARK_DIR}/batchnorm.cc
|
||||
${BENCHMARK_DIR}/batchnorm2.cc
|
||||
${BENCHMARK_DIR}/tptest.cc
|
||||
|
|
|
|||
|
|
@ -967,41 +967,35 @@ static void PermuteInput(api::GraphRef& graph, api::NodeRef& node, size_t i, con
|
|||
node.SetInput(i, gather_output);
|
||||
}
|
||||
|
||||
// static bool HandleResize(HandlerArgs& args) {
|
||||
// auto inputs = args.node.Inputs();
|
||||
// int64_t rank_int = gsl::narrow_cast<int64_t>(args.perm.size());
|
||||
//
|
||||
// auto p = ChannelFirstToLastPerm(rank_int);
|
||||
// auto& perm = p == args.perm ? args.perm : args.perm_inv;
|
||||
// auto& perm_inv = p == args.perm ? args.perm_inv : args.perm;
|
||||
//
|
||||
// if (args.ctx.opset < 11) {
|
||||
// PermuteInput(args.ctx.graph, args.node, 1, perm);
|
||||
// } else {
|
||||
// if (inputs[1] != "") {
|
||||
// std::vector<int64_t> double_perm_inv = perm;
|
||||
// double_perm_inv.reserve(2 * args.perm.size());
|
||||
// for (int64_t p1 : perm) {
|
||||
// double_perm_inv.push_back(p1 + rank_int);
|
||||
// }
|
||||
// PermuteInput(args.ctx.graph, args.node, 1, double_perm_inv);
|
||||
// }
|
||||
// for (size_t i = 2; i < inputs.size(); ++i) {
|
||||
// if (inputs[i] != "") {
|
||||
// PermuteInput(args.ctx.graph, args.node, i, perm);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TransposeFirstInput(args.ctx, args.node, perm);
|
||||
// TransposeOutputs(args.ctx, args.node, perm_inv);
|
||||
//
|
||||
// SwapNodeOpTypeAndDomain(args.ctx.graph, args.node, args.node.OpType(), "com.microsoft.nhwc");
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
static bool HandleResize(HandlerArgs& args) {
|
||||
auto inputs = args.node.Inputs();
|
||||
int64_t rank_int = gsl::narrow_cast<int64_t>(args.perm.size());
|
||||
|
||||
// constexpr HandlerInfo resize_handler = {&FirstInput, &HandleResize};
|
||||
if (args.ctx.opset < 11) {
|
||||
PermuteInput(args.ctx.graph, args.node, 1, args.perm_inv);
|
||||
} else {
|
||||
if (inputs[1] != "") {
|
||||
std::vector<int64_t> double_perm_inv = args.perm_inv;
|
||||
double_perm_inv.reserve(2 * args.perm_inv.size());
|
||||
for (int64_t p : args.perm_inv) {
|
||||
double_perm_inv.push_back(p + rank_int);
|
||||
}
|
||||
PermuteInput(args.ctx.graph, args.node, 1, double_perm_inv);
|
||||
}
|
||||
for (size_t i = 2; i < inputs.size(); ++i) {
|
||||
if (inputs[i] != "") {
|
||||
PermuteInput(args.ctx.graph, args.node, i, args.perm_inv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TransposeFirstInput(args.ctx, args.node, args.perm_inv);
|
||||
TransposeOutputs(args.ctx, args.node, args.perm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr HandlerInfo resize_handler = {&FirstInput, &HandleResize};
|
||||
|
||||
static bool HandlePad(HandlerArgs& args) {
|
||||
size_t rank = args.perm.size();
|
||||
|
|
@ -1697,9 +1691,7 @@ static const std::unordered_map<std::string_view, const HandlerInfo&> handler_ma
|
|||
{"Split", split_handler},
|
||||
{"Shape", shape_handler},
|
||||
{"Pad", pad_handler},
|
||||
// Todo: renable resize handler after adding NHWC support in upsample op on cpu
|
||||
// https://github.com/microsoft/onnxruntime/issues/9857
|
||||
// {"Resize", resize_handler},
|
||||
{"Resize", resize_handler},
|
||||
{"ReduceSum", reduce_sum_handler},
|
||||
|
||||
{"ReduceLogSum", reduce_op_handler},
|
||||
|
|
|
|||
|
|
@ -397,39 +397,24 @@ static Status UpsampleLinear(const T* input,
|
|||
}
|
||||
*/
|
||||
|
||||
struct BilinearParams {
|
||||
std::vector<float> x_original;
|
||||
std::vector<float> y_original;
|
||||
|
||||
BufferUniquePtr idx_scale_data_buffer_holder;
|
||||
|
||||
int64_t* input_width_mul_y1;
|
||||
int64_t* input_width_mul_y2;
|
||||
|
||||
int64_t* in_x1;
|
||||
int64_t* in_x2;
|
||||
|
||||
float* dx1;
|
||||
float* dx2;
|
||||
|
||||
float* dy1;
|
||||
float* dy2;
|
||||
};
|
||||
|
||||
// The following method supports a 4-D input in 'Linear mode'
|
||||
// that amounts to 'Bilinear' Upsampling/Resizing in the sense that it assumes
|
||||
// the scale values for the outermost 2 dimensions are 1.
|
||||
// 1. the scale values for the outermost 2 dimensions are 1 or
|
||||
// 2. the scale values for the outermost and innermost dimensions are 1
|
||||
// This is the common use-case where the 4-D input (batched multi-channel images)
|
||||
// is usually of shape [N, C, H, W] and the scales are [1.0, 1.0, height_scale, width_scale]
|
||||
static BilinearParams SetupUpsampleBilinear(int64_t input_height,
|
||||
int64_t input_width,
|
||||
int64_t output_height,
|
||||
int64_t output_width,
|
||||
float height_scale,
|
||||
float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate) {
|
||||
// is usually of shapes:
|
||||
// - [N, C, H, W] and the scales are [1.0, 1.0, height_scale, width_scale]
|
||||
// - [N, H, W, C] and the scales are [1.0, height_scale, width_scale, 1.0]
|
||||
BilinearParams SetupUpsampleBilinear(const int64_t input_height,
|
||||
const int64_t input_width,
|
||||
const int64_t output_height,
|
||||
const int64_t output_width,
|
||||
const float height_scale,
|
||||
const float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate,
|
||||
bool is_nchw) {
|
||||
BilinearParams p;
|
||||
|
||||
p.x_original.reserve(output_width);
|
||||
|
|
@ -471,8 +456,9 @@ static BilinearParams SetupUpsampleBilinear(int64_t input_height,
|
|||
p.dx2 = p.dx1 + output_width;
|
||||
|
||||
// Start processing
|
||||
auto roi_y_start = roi.size() / 2 - 2;
|
||||
auto roi_y_end = roi.size() - 2;
|
||||
const size_t height_rindex = is_nchw ? 1 : 2;
|
||||
auto roi_y_start = roi.size() / 2 - (height_rindex + 1);
|
||||
auto roi_y_end = roi.size() - (height_rindex + 1);
|
||||
for (int64_t y = 0; y < output_height; ++y) {
|
||||
float in_y = height_scale == 1 ? static_cast<float>(y)
|
||||
: get_original_coordinate(static_cast<float>(y), height_scale,
|
||||
|
|
@ -496,8 +482,9 @@ static BilinearParams SetupUpsampleBilinear(int64_t input_height,
|
|||
p.input_width_mul_y2[y] = input_width * in_y2;
|
||||
}
|
||||
|
||||
auto roi_x_start = roi.size() / 2 - 1;
|
||||
auto roi_x_end = roi.size() - 1;
|
||||
const size_t width_rindex = is_nchw ? 0 : 1;
|
||||
auto roi_x_start = roi.size() / 2 - (width_rindex + 1);
|
||||
auto roi_x_end = roi.size() - (width_rindex + 1);
|
||||
for (int64_t x = 0; x < output_width; ++x) {
|
||||
float in_x = width_scale == 1 ? static_cast<float>(x)
|
||||
: get_original_coordinate(static_cast<float>(x),
|
||||
|
|
@ -522,59 +509,6 @@ static BilinearParams SetupUpsampleBilinear(int64_t input_height,
|
|||
return p;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void UpsampleBilinear(int64_t batch_size,
|
||||
int64_t num_channels,
|
||||
int64_t input_height,
|
||||
int64_t input_width,
|
||||
int64_t output_height,
|
||||
int64_t output_width,
|
||||
float height_scale,
|
||||
float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
bool use_extrapolation,
|
||||
float extrapolation_value,
|
||||
const T* XdataBase,
|
||||
T* YdataBase,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate,
|
||||
concurrency::ThreadPool* tp) {
|
||||
BilinearParams p = SetupUpsampleBilinear(input_height, input_width, output_height, output_width,
|
||||
height_scale, width_scale, roi,
|
||||
alloc, get_original_coordinate);
|
||||
|
||||
for (int64_t n = 0; n < batch_size; ++n) {
|
||||
concurrency::ThreadPool::TrySimpleParallelFor(
|
||||
tp, num_channels,
|
||||
[&](std::ptrdiff_t c) {
|
||||
const T* Xdata = XdataBase + (n * num_channels + c) * (input_height * input_width);
|
||||
T* Ydata = YdataBase + (n * num_channels + c) * (output_height * output_width);
|
||||
for (int64_t y = 0; y < output_height; ++y) {
|
||||
for (int64_t x = 0; x < output_width; ++x) {
|
||||
// when use_extrapolation is set and original index of x or y is out of the dim range
|
||||
// then use extrapolation_value as the output value.
|
||||
if (use_extrapolation &&
|
||||
((p.y_original[y] < 0 || p.y_original[y] > static_cast<float>(input_height - 1)) ||
|
||||
(p.x_original[x] < 0 || p.x_original[x] > static_cast<float>(input_width - 1)))) {
|
||||
Ydata[output_width * y + x] = static_cast<T>(extrapolation_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
T X11 = Xdata[p.input_width_mul_y1[y] + p.in_x1[x]];
|
||||
T X21 = Xdata[p.input_width_mul_y1[y] + p.in_x2[x]];
|
||||
T X12 = Xdata[p.input_width_mul_y2[y] + p.in_x1[x]];
|
||||
T X22 = Xdata[p.input_width_mul_y2[y] + p.in_x2[x]];
|
||||
|
||||
Ydata[output_width * y + x] = static_cast<T>(p.dx2[x] * p.dy2[y] * X11 +
|
||||
p.dx1[x] * p.dy2[y] * X21 +
|
||||
p.dx2[x] * p.dy1[y] * X12 +
|
||||
p.dx1[x] * p.dy1[y] * X22);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct TrilinearParams {
|
||||
std::vector<float> x_original;
|
||||
std::vector<float> y_original;
|
||||
|
|
@ -1065,25 +999,78 @@ Status Upsample<T>::BaseCompute(OpKernelContext* context,
|
|||
case UpsampleMode::LINEAR: {
|
||||
// Supports 'bilinear' and 'trilinear' sampling only
|
||||
|
||||
//'bilinear' == 2-D input or 4-D input with outermost 2 scales as 1
|
||||
//'bilinear' == 2-D input or 4-D input with outermost 2 scales as 1 or
|
||||
// 4-D input with outermost and innermost scales as 1
|
||||
if (dims.size() == 2 || dims.size() == 4) {
|
||||
bool is_2D = dims.size() == 2;
|
||||
bool is_nchw = true;
|
||||
|
||||
const int64_t batch_size = is_2D ? 1 : dims[0];
|
||||
const int64_t num_channels = is_2D ? 1 : dims[1];
|
||||
const int64_t input_height = is_2D ? dims[0] : dims[2];
|
||||
const int64_t input_width = is_2D ? dims[1] : dims[3];
|
||||
int64_t batch_size;
|
||||
int64_t num_channels;
|
||||
int64_t input_height;
|
||||
int64_t input_width;
|
||||
|
||||
const int64_t output_height = is_2D ? output_dims[0] : output_dims[2];
|
||||
const int64_t output_width = is_2D ? output_dims[1] : output_dims[3];
|
||||
int64_t output_height;
|
||||
int64_t output_width;
|
||||
|
||||
float height_scale;
|
||||
float width_scale;
|
||||
|
||||
if (is_2D) {
|
||||
batch_size = 1;
|
||||
num_channels = 1;
|
||||
input_height = dims[0];
|
||||
input_width = dims[1];
|
||||
|
||||
output_height = output_dims[0];
|
||||
output_width = output_dims[1];
|
||||
|
||||
height_scale = scales[0];
|
||||
width_scale = scales[1];
|
||||
} else {
|
||||
if (scales[1] == 1.0f) {
|
||||
batch_size = dims[0];
|
||||
num_channels = dims[1];
|
||||
input_height = dims[2];
|
||||
input_width = dims[3];
|
||||
|
||||
output_height = output_dims[2];
|
||||
output_width = output_dims[3];
|
||||
|
||||
height_scale = scales[2];
|
||||
width_scale = scales[3];
|
||||
} else {
|
||||
ORT_ENFORCE(scales[3] == 1.0f, "4-D input with innermost scale (usually channel of NHWC) as 1.");
|
||||
is_nchw = false;
|
||||
|
||||
batch_size = dims[0];
|
||||
num_channels = dims[3];
|
||||
input_height = dims[1];
|
||||
input_width = dims[2];
|
||||
|
||||
output_height = output_dims[1];
|
||||
output_width = output_dims[2];
|
||||
|
||||
height_scale = scales[1];
|
||||
width_scale = scales[2];
|
||||
}
|
||||
}
|
||||
|
||||
AllocatorPtr alloc;
|
||||
ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&alloc));
|
||||
UpsampleBilinear(batch_size, num_channels, input_height, input_width, output_height, output_width,
|
||||
is_2D ? scales[0] : scales[2], is_2D ? scales[1] : scales[3], roi,
|
||||
use_extrapolation_, extrapolation_value_, X->Data<T>(),
|
||||
Y->MutableData<T>(), alloc, get_original_coordinate_,
|
||||
output_height * output_width > 64 ? context->GetOperatorThreadPool() : nullptr);
|
||||
if (is_nchw) {
|
||||
UpsampleBilinear(batch_size, num_channels, input_height, input_width, output_height, output_width,
|
||||
height_scale, width_scale, roi,
|
||||
use_extrapolation_, extrapolation_value_, X->Data<T>(),
|
||||
Y->MutableData<T>(), alloc, get_original_coordinate_,
|
||||
output_height * output_width > 64 ? context->GetOperatorThreadPool() : nullptr);
|
||||
} else {
|
||||
NhwcUpsampleBilinear(batch_size, num_channels, input_height, input_width, output_height, output_width,
|
||||
height_scale, width_scale, roi,
|
||||
use_extrapolation_, extrapolation_value_, X->Data<T>(),
|
||||
Y->MutableData<T>(), alloc, get_original_coordinate_,
|
||||
output_height * output_width * num_channels > 64 ? context->GetOperatorThreadPool() : nullptr);
|
||||
}
|
||||
return Status::OK();
|
||||
} else if (dims.size() == 3 || dims.size() == 5) {
|
||||
//'trilinear' == 3-D input or 5-D input with outermost 2 scales as 1
|
||||
|
|
|
|||
|
|
@ -50,6 +50,25 @@ enum ResizeNearestMode {
|
|||
NearestModeCount = 5,
|
||||
};
|
||||
|
||||
struct BilinearParams {
|
||||
std::vector<float> x_original;
|
||||
std::vector<float> y_original;
|
||||
|
||||
BufferUniquePtr idx_scale_data_buffer_holder;
|
||||
|
||||
int64_t* input_width_mul_y1;
|
||||
int64_t* input_width_mul_y2;
|
||||
|
||||
int64_t* in_x1;
|
||||
int64_t* in_x2;
|
||||
|
||||
float* dx1;
|
||||
float* dx2;
|
||||
|
||||
float* dy1;
|
||||
float* dy2;
|
||||
};
|
||||
|
||||
class UpsampleBase {
|
||||
protected:
|
||||
UpsampleBase(const OpKernelInfo& info) : scales_cached_(false), roi_cached_(false), use_extrapolation_(false) {
|
||||
|
|
@ -378,7 +397,125 @@ class Upsample : public UpsampleBase, public OpKernel {
|
|||
const gsl::span<const int64_t>& output_dims) const;
|
||||
};
|
||||
|
||||
BilinearParams SetupUpsampleBilinear(const int64_t input_height,
|
||||
const int64_t input_width,
|
||||
const int64_t output_height,
|
||||
const int64_t output_width,
|
||||
const float height_scale,
|
||||
const float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate,
|
||||
bool is_nchw);
|
||||
|
||||
template <typename T>
|
||||
void UpsampleBilinear(const int64_t batch_size,
|
||||
const int64_t num_channels,
|
||||
const int64_t input_height,
|
||||
const int64_t input_width,
|
||||
const int64_t output_height,
|
||||
const int64_t output_width,
|
||||
const float height_scale,
|
||||
const float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
const bool use_extrapolation,
|
||||
const float extrapolation_value,
|
||||
const T* const XdataBase,
|
||||
T* const YdataBase,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate,
|
||||
concurrency::ThreadPool* tp) {
|
||||
BilinearParams p = SetupUpsampleBilinear(input_height, input_width, output_height, output_width,
|
||||
height_scale, width_scale, roi,
|
||||
alloc, get_original_coordinate, true);
|
||||
for (int64_t n = 0; n < batch_size; ++n) {
|
||||
concurrency::ThreadPool::TrySimpleParallelFor(
|
||||
tp, num_channels,
|
||||
[&](std::ptrdiff_t c) {
|
||||
const T* Xdata = XdataBase + (n * num_channels + c) * (input_height * input_width);
|
||||
T* Ydata = YdataBase + (n * num_channels + c) * (output_height * output_width);
|
||||
for (int64_t y = 0; y < output_height; ++y) {
|
||||
for (int64_t x = 0; x < output_width; ++x) {
|
||||
// when use_extrapolation is set and original index of x or y is out of the dim range
|
||||
// then use extrapolation_value as the output value.
|
||||
if (use_extrapolation &&
|
||||
((p.y_original[y] < 0 || p.y_original[y] > static_cast<float>(input_height - 1)) ||
|
||||
(p.x_original[x] < 0 || p.x_original[x] > static_cast<float>(input_width - 1)))) {
|
||||
Ydata[output_width * y + x] = static_cast<T>(extrapolation_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
T X11 = Xdata[p.input_width_mul_y1[y] + p.in_x1[x]];
|
||||
T X21 = Xdata[p.input_width_mul_y1[y] + p.in_x2[x]];
|
||||
T X12 = Xdata[p.input_width_mul_y2[y] + p.in_x1[x]];
|
||||
T X22 = Xdata[p.input_width_mul_y2[y] + p.in_x2[x]];
|
||||
|
||||
Ydata[output_width * y + x] = static_cast<T>(p.dx2[x] * p.dy2[y] * X11 +
|
||||
p.dx1[x] * p.dy2[y] * X21 +
|
||||
p.dx2[x] * p.dy1[y] * X12 +
|
||||
p.dx1[x] * p.dy1[y] * X22);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NhwcUpsampleBilinear(const int64_t batch_size,
|
||||
const int64_t num_channels,
|
||||
const int64_t input_height,
|
||||
const int64_t input_width,
|
||||
const int64_t output_height,
|
||||
const int64_t output_width,
|
||||
const float height_scale,
|
||||
const float width_scale,
|
||||
const std::vector<float>& roi,
|
||||
const bool use_extrapolation,
|
||||
const float extrapolation_value,
|
||||
const T* const XdataBase,
|
||||
T* const YdataBase,
|
||||
AllocatorPtr& alloc,
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate,
|
||||
concurrency::ThreadPool* tp) {
|
||||
BilinearParams p = SetupUpsampleBilinear(input_height, input_width, output_height, output_width,
|
||||
height_scale, width_scale, roi,
|
||||
alloc, get_original_coordinate, false);
|
||||
for (int64_t n = 0; n < batch_size; ++n) {
|
||||
const T* Xdata = XdataBase + n * (input_height * input_width) * num_channels;
|
||||
T* Ydata = YdataBase + n * (output_height * output_width) * num_channels;
|
||||
concurrency::ThreadPool::TryParallelFor(
|
||||
tp, output_height * output_width,
|
||||
static_cast<double>(num_channels * 2),
|
||||
[&](std::ptrdiff_t first, std::ptrdiff_t last) {
|
||||
for (std::ptrdiff_t i = first; i < last; ++i) {
|
||||
const int64_t x = i % output_width;
|
||||
const int64_t y = i / output_width;
|
||||
for (int64_t c = 0; c < num_channels; ++c) {
|
||||
// when use_extrapolation is set and original index of x or y is out of the dim range
|
||||
// then use extrapolation_value as the output value.
|
||||
if (use_extrapolation &&
|
||||
((p.y_original[y] < 0 || p.y_original[y] > static_cast<float>(input_height - 1)) ||
|
||||
(p.x_original[x] < 0 || p.x_original[x] > static_cast<float>(input_width - 1)))) {
|
||||
Ydata[(output_width * y + x) * num_channels + c] = static_cast<T>(extrapolation_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
T X11 = Xdata[(p.input_width_mul_y1[y] + p.in_x1[x]) * num_channels + c];
|
||||
T X21 = Xdata[(p.input_width_mul_y1[y] + p.in_x2[x]) * num_channels + c];
|
||||
T X12 = Xdata[(p.input_width_mul_y2[y] + p.in_x1[x]) * num_channels + c];
|
||||
T X22 = Xdata[(p.input_width_mul_y2[y] + p.in_x2[x]) * num_channels + c];
|
||||
|
||||
Ydata[(output_width * y + x) * num_channels + c] = static_cast<T>(p.dx2[x] * p.dy2[y] * X11 +
|
||||
p.dx1[x] * p.dy2[y] * X21 +
|
||||
p.dx2[x] * p.dy1[y] * X12 +
|
||||
p.dx1[x] * p.dy1[y] * X22);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace onnxruntime
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
83
onnxruntime/test/onnx/microbenchmark/resize.cc
Normal file
83
onnxruntime/test/onnx/microbenchmark/resize.cc
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <limits>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include "core/common/safeint.h"
|
||||
#include "core/framework/allocator.h"
|
||||
#include "core/mlas/lib/mlasi.h"
|
||||
#include "core/providers/cpu/tensor/upsample.h"
|
||||
#include "core/util/math_cpuonly.h"
|
||||
#include "core/util/qmath.h"
|
||||
#include "core/util/thread_utils.h"
|
||||
|
||||
using namespace onnxruntime;
|
||||
|
||||
template <typename T>
|
||||
static void BM_NhwcUpsampleBilinear(benchmark::State& state) {
|
||||
const int64_t output_height = static_cast<int64_t>(state.range(0));
|
||||
const int64_t output_width = static_cast<int64_t>(state.range(1));
|
||||
constexpr int64_t batch_size = 1;
|
||||
constexpr int64_t num_channels = 256;
|
||||
constexpr int64_t input_height = 32;
|
||||
constexpr int64_t input_width = 32;
|
||||
const int64_t height_scale = output_height / input_height;
|
||||
const int64_t width_scale = output_width / input_width;
|
||||
const std::vector<float> roi{0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
constexpr bool use_extrapolation = false;
|
||||
constexpr float extrapolation_value = 0;
|
||||
constexpr size_t XdataBaseSize = batch_size * num_channels * input_height * input_width;
|
||||
const T* const XdataBase = GenerateArrayWithRandomValue<T>(XdataBaseSize, std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
||||
const size_t YdataBaseSize = batch_size * num_channels * output_height * output_width;
|
||||
T* const YdataBase = (T*)aligned_alloc(sizeof(T) * YdataBaseSize, 64);
|
||||
AllocatorPtr alloc = std::make_shared<CPUAllocator>();
|
||||
const GetOriginalCoordinateFunc& get_original_coordinate =
|
||||
[](float x_resized, float x_scale, float, float, float, float) {
|
||||
return x_resized / x_scale;
|
||||
};
|
||||
OrtThreadPoolParams tpo;
|
||||
tpo.auto_set_affinity = true;
|
||||
std::unique_ptr<concurrency::ThreadPool> tp(
|
||||
concurrency::CreateThreadPool(&onnxruntime::Env::Default(), tpo, concurrency::ThreadPoolType::INTRA_OP));
|
||||
|
||||
for (auto _ : state) {
|
||||
NhwcUpsampleBilinear(batch_size, num_channels, input_height, input_width, output_height, output_width,
|
||||
static_cast<float>(height_scale), static_cast<float>(width_scale), roi,
|
||||
use_extrapolation, extrapolation_value, XdataBase,
|
||||
YdataBase, alloc, get_original_coordinate,
|
||||
output_height * output_width * num_channels > 64 ? tp.get() : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_NhwcUpsampleBilinear, uint8_t)
|
||||
->MeasureProcessCPUTime()
|
||||
->UseRealTime()
|
||||
->Unit(benchmark::TimeUnit::kNanosecond)
|
||||
->Args({32, 32})
|
||||
->Args({64, 64})
|
||||
->Args({96, 96})
|
||||
->Args({128, 128})
|
||||
->Args({160, 160})
|
||||
->Args({1, 1000000});
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_NhwcUpsampleBilinear, int8_t)
|
||||
->MeasureProcessCPUTime()
|
||||
->UseRealTime()
|
||||
->Unit(benchmark::TimeUnit::kNanosecond)
|
||||
->Args({32, 32})
|
||||
->Args({64, 64})
|
||||
->Args({96, 96})
|
||||
->Args({128, 128})
|
||||
->Args({160, 160})
|
||||
->Args({1, 1000000});
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_NhwcUpsampleBilinear, float)
|
||||
->MeasureProcessCPUTime()
|
||||
->UseRealTime()
|
||||
->Unit(benchmark::TimeUnit::kNanosecond)
|
||||
->Args({32, 32})
|
||||
->Args({64, 64})
|
||||
->Args({96, 96})
|
||||
->Args({128, 128})
|
||||
->Args({160, 160})
|
||||
->Args({1, 1000000});
|
||||
|
|
@ -291,212 +291,209 @@ TEST(TransposeOptimizerTests, TestPadNonconst) {
|
|||
/*opset_version*/ 11);
|
||||
}
|
||||
|
||||
// Todo: renable tests on resize transformer after adding NHWC support in upsample op on cpu
|
||||
// https://github.com/microsoft/onnxruntime/issues/9857
|
||||
TEST(TransposeOptimizerTests, TestResize) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* const_1 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
|
||||
// TEST(TransposeOptimizerTests, TestResize) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* const_1 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// builder.AddNode("Resize", {transpose_1_out_0, const_1}, {resize_1_out_0});
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 10);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeOpset11) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* const_1 = builder.MakeInitializer<float>({8}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f});
|
||||
// auto* const_2 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// builder.AddNode("Resize", {transpose_1_out_0, const_1, const_2}, {resize_1_out_0});
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 11);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeOpset15) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* const_1 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
// auto empty_arg = NodeArg("", nullptr);
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// builder.AddNode("Resize", {transpose_1_out_0, &empty_arg, const_1}, {resize_1_out_0});
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 15);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeSizeRoi) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* const_1 = builder.MakeInitializer<float>({8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
// auto* const_2 = builder.MakeInitializer<int64_t>({4}, {10, 9, 8, 7});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
// auto empty_arg = NodeArg("", nullptr);
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, const_1, &empty_arg, const_2}, {resize_1_out_0});
|
||||
// resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 15);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeRoiScalesZeroRank0) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input = builder.MakeInput<uint8_t>({1, 512, 512, 3},
|
||||
// std::numeric_limits<uint8_t>::min(),
|
||||
// std::numeric_limits<uint8_t>::max());
|
||||
// auto* resize_in_roi = builder.MakeInitializer<float>({0}, {});
|
||||
// auto* resize_in_scales = builder.MakeInitializer<float>({0}, {});
|
||||
// auto* resize_in_sizes = builder.MakeInitializer<int64_t>({4}, {1, 256, 32, 32});
|
||||
//
|
||||
// auto* transpose1_out_transposed = builder.MakeIntermediate();
|
||||
// auto* resize_out_Y = builder.MakeIntermediate();
|
||||
// auto* output = builder.MakeOutput();
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input}, {transpose1_out_transposed});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// builder.AddNode("Resize",
|
||||
// {transpose1_out_transposed, resize_in_roi, resize_in_scales, resize_in_sizes},
|
||||
// {resize_out_Y});
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_out_Y}, {output});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeNonconst) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* input1_arg = MakeInput<float>(builder, {{8}}, {8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
// auto* input2_arg = MakeInput<float>(builder, {{4}}, {4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, input1_arg, input2_arg}, {resize_1_out_0});
|
||||
// resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 11);
|
||||
// }
|
||||
//
|
||||
// TEST(TransposeOptimizerTests, TestResizeNonconstOpset13) {
|
||||
// auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
// auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
// auto* input1_arg = MakeInput<float>(builder, {{8}}, {8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
// auto* input2_arg = MakeInput<float>(builder, {{4}}, {4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
// auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
// auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
//
|
||||
// auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
// transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
// auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, input1_arg, input2_arg}, {resize_1_out_0});
|
||||
// resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
// auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
// transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
// };
|
||||
//
|
||||
// auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
// int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
// EXPECT_EQ(transpose_cost, 0);
|
||||
// };
|
||||
//
|
||||
// TransformerTester(build_test_case_1,
|
||||
// check_optimized_graph_1,
|
||||
// TransformerLevel::Default,
|
||||
// TransformerLevel::Level1,
|
||||
// /*opset_version*/ 13);
|
||||
// }
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
builder.AddNode("Resize", {transpose_1_out_0, const_1}, {resize_1_out_0});
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 10);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeOpset11) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* const_1 = builder.MakeInitializer<float>({8}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f});
|
||||
auto* const_2 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
builder.AddNode("Resize", {transpose_1_out_0, const_1, const_2}, {resize_1_out_0});
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 11);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeOpset15) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* const_1 = builder.MakeInitializer<float>({4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
auto empty_arg = NodeArg("", nullptr);
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
builder.AddNode("Resize", {transpose_1_out_0, &empty_arg, const_1}, {resize_1_out_0});
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 15);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeSizeRoi) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* const_1 = builder.MakeInitializer<float>({8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
auto* const_2 = builder.MakeInitializer<int64_t>({4}, {10, 9, 8, 7});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
auto empty_arg = NodeArg("", nullptr);
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, const_1, &empty_arg, const_2}, {resize_1_out_0});
|
||||
resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 15);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeRoiScalesZeroRank0) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input = builder.MakeInput<uint8_t>({1, 512, 512, 3},
|
||||
std::numeric_limits<uint8_t>::min(),
|
||||
std::numeric_limits<uint8_t>::max());
|
||||
auto* resize_in_roi = builder.MakeInitializer<float>({0}, {});
|
||||
auto* resize_in_scales = builder.MakeInitializer<float>({0}, {});
|
||||
auto* resize_in_sizes = builder.MakeInitializer<int64_t>({4}, {1, 256, 32, 32});
|
||||
|
||||
auto* transpose1_out_transposed = builder.MakeIntermediate();
|
||||
auto* resize_out_Y = builder.MakeIntermediate();
|
||||
auto* output = builder.MakeOutput();
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input}, {transpose1_out_transposed});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
builder.AddNode("Resize",
|
||||
{transpose1_out_transposed, resize_in_roi, resize_in_scales, resize_in_sizes},
|
||||
{resize_out_Y});
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_out_Y}, {output});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeNonconst) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* input1_arg = MakeInput<float>(builder, {{8}}, {8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
auto* input2_arg = MakeInput<float>(builder, {{4}}, {4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, input1_arg, input2_arg}, {resize_1_out_0});
|
||||
resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 11);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestResizeNonconstOpset13) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
auto* input0_arg = MakeInput<float>(builder, {{4, -1, 2, -1}}, {4, 6, 2, 10}, 0.0, 1.0);
|
||||
auto* input1_arg = MakeInput<float>(builder, {{8}}, {8}, {0.1f, 0.2f, 0.3f, 0.4f, 0.9f, 0.8f, 0.7f, 0.6f});
|
||||
auto* input2_arg = MakeInput<float>(builder, {{4}}, {4}, {0.3f, 2.5f, 1.0f, 0.7f});
|
||||
auto* transpose_1_out_0 = builder.MakeIntermediate();
|
||||
auto* resize_1_out_0 = builder.MakeIntermediate();
|
||||
auto* transpose_2_out_0 = builder.MakeOutput();
|
||||
|
||||
auto& transpose_1 = builder.AddNode("Transpose", {input0_arg}, {transpose_1_out_0});
|
||||
transpose_1.AddAttribute("perm", std::vector<int64_t>{0, 3, 1, 2});
|
||||
auto& resize_1 = builder.AddNode("Resize", {transpose_1_out_0, input1_arg, input2_arg}, {resize_1_out_0});
|
||||
resize_1.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
auto& transpose_2 = builder.AddNode("Transpose", {resize_1_out_0}, {transpose_2_out_0});
|
||||
transpose_2.AddAttribute("perm", std::vector<int64_t>{0, 2, 3, 1});
|
||||
};
|
||||
|
||||
auto check_optimized_graph_1 = [&](InferenceSessionWrapper& session) {
|
||||
int transpose_cost = EstimateTransposeCost(session.GetGraph());
|
||||
EXPECT_EQ(transpose_cost, 0);
|
||||
};
|
||||
|
||||
TransformerTester(build_test_case_1,
|
||||
check_optimized_graph_1,
|
||||
TransformerLevel::Default,
|
||||
TransformerLevel::Level1,
|
||||
/*opset_version*/ 13);
|
||||
}
|
||||
|
||||
TEST(TransposeOptimizerTests, TestAdd) {
|
||||
auto build_test_case_1 = [&](ModelTestBuilder& builder) {
|
||||
|
|
@ -4013,6 +4010,5 @@ TEST(TransposeOptimizerTests, RegressionTest_GitHubIssue10305) {
|
|||
ASSERT_STATUS_OK(session_object.Load(model_uri));
|
||||
ASSERT_STATUS_OK(session_object.Initialize()); // optimizers run during initialization
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -65,6 +65,38 @@ TEST(ResizeOpTest, ResizeOpLinearDownSampleTest_tf_crop_and_resize_with_extrapol
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_tf_crop_and_resize_with_extrapolation) {
|
||||
OpTester test("Resize", 13);
|
||||
std::vector<float> scales{1.0f, 0.8f, 0.8f, 1.0f};
|
||||
std::vector<float> roi{0.0f, 0.4f, 0.6f, 0.0f, 1.0f, 1.2f, 1.7f, 1.0f};
|
||||
|
||||
test.AddAttribute("mode", "linear");
|
||||
test.AddAttribute("coordinate_transformation_mode", "tf_crop_and_resize");
|
||||
test.AddAttribute("extrapolation_value", 10.0f);
|
||||
|
||||
constexpr int64_t N = 1, H = 4, W = 4, C = 1;
|
||||
std::vector<float> X = {
|
||||
1.0f, 2.0f, 3.0f, 4.0f,
|
||||
5.0f, 6.0f, 7.0f, 8.0f,
|
||||
9.0f, 10.0f, 11.0f, 12.0f,
|
||||
13.0f, 14.0f, 15.0f, 16.0f};
|
||||
|
||||
test.AddInput<float>("X", {N, H, W, C}, X);
|
||||
test.AddInput<float>("roi", {8}, roi);
|
||||
test.AddInput<float>("scales", {4}, scales);
|
||||
|
||||
std::vector<float> Y = {7.6000004f, 10.0f, 10.0f,
|
||||
12.400001f, 10.f, 10.0f,
|
||||
10.0f, 10.0f, 10.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, static_cast<int64_t>(H * scales[1]), static_cast<int64_t>(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(ResizeOpTest, ResizeOpLinearDownSampleTest_4DBilinear) {
|
||||
OpTester test("Resize", 13);
|
||||
std::vector<float> roi{};
|
||||
|
|
@ -689,10 +721,10 @@ class ResizeOpTester : public OpTester {
|
|||
OpTester::AddNodes(graph, graph_input_defs, graph_output_defs, add_attribute_funcs);
|
||||
|
||||
// set the Graph inputs to just X and roi (exclude 'scales') so the 'scales' are a constant initializer
|
||||
if(scales_in_initializer_) {
|
||||
if (scales_in_initializer_) {
|
||||
graph.SetInputs({graph.GetNodeArg(graph_input_defs[0]->Name()),
|
||||
graph.GetNodeArg(graph_input_defs[1]->Name())});
|
||||
if(sizes_in_initializer_) {
|
||||
if (sizes_in_initializer_) {
|
||||
ASSERT_TRUE(graph_input_defs.size() == 4);
|
||||
} else {
|
||||
ASSERT_TRUE(graph_input_defs.size() == 3);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,59 @@ TEST(UpsampleOpTest, UpsampleOpNearestTest) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearestTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 3.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 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, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearestTest_int32) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -73,6 +126,59 @@ TEST(UpsampleOpTest, UpsampleOpNearestTest_int32) {
|
|||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearestTest_int32) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 3.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 2;
|
||||
std::vector<int32_t> X = {1, 3,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
7, 9};
|
||||
|
||||
test.AddInput<int32_t>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<int32_t> Y = {
|
||||
1, 3,
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
1, 3,
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
7, 9,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
7, 9};
|
||||
|
||||
test.AddOutput<int32_t>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearestTest_uint8) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -104,6 +210,59 @@ TEST(UpsampleOpTest, UpsampleOpNearestTest_uint8) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearestTest_uint8) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 3.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 2;
|
||||
std::vector<uint8_t> X = {1, 3,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
7, 9};
|
||||
|
||||
test.AddInput<uint8_t>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<uint8_t> Y = {
|
||||
1, 3,
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
1, 3,
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
7, 9,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
7, 9};
|
||||
|
||||
test.AddOutput<uint8_t>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearest2XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -135,6 +294,51 @@ TEST(UpsampleOpTest, UpsampleOpNearest2XTest) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearest2XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 2.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 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, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearest222XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -176,6 +380,71 @@ TEST(UpsampleOpTest, UpsampleOpNearest222XTest) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearest222XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{2.0f, 2.0f, 2.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 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, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
7.0f, 9.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {(int64_t)(N * scales[0]), (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearest15XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -207,6 +476,47 @@ TEST(UpsampleOpTest, UpsampleOpNearest15XTest) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearest15XTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 1.5f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 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, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
1.0f, 3.0f,
|
||||
1.0f, 3.0f,
|
||||
3.0f, 5.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f,
|
||||
|
||||
3.0f, 5.0f,
|
||||
3.0f, 5.0f,
|
||||
7.0f, 9.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearestTest_NoScale) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -264,6 +574,51 @@ TEST(UpsampleOpTest, UpsampleOpNearest2XTest_int32) {
|
|||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports<nvinfer1::query::AbstractTensor>&): Assertion `!formats.empty()' failed
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearest2XTest_int32) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 2.0f, 1.0f};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 2;
|
||||
std::vector<int32_t> X = {1, 3,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
7, 9};
|
||||
|
||||
test.AddInput<int32_t>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<int32_t> Y = {
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9};
|
||||
|
||||
test.AddOutput<int32_t>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOp4DBilinearTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -292,7 +647,111 @@ TEST(UpsampleOpTest, UpsampleOp4DBilinearTest) {
|
|||
7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.0f, 9.0f, 9.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: results mismatch
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOp4D1CBilinearTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 4.0f, 1.0f};
|
||||
test.AddAttribute("mode", "linear");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 2, H = 2, W = 3, C = 1;
|
||||
std::vector<float> X = {1.0f, 2.0f, 3.0f,
|
||||
4.0f, 5.0f, 6.0f,
|
||||
|
||||
7.0f, 8.0f, 9.0f,
|
||||
10.0f, 11.0f, 12.0f};
|
||||
|
||||
test.AddInput<float>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.25f, 2.5f, 2.75f, 3.0f, 3.0f, 3.0f, 3.0f,
|
||||
2.5f, 2.75f, 3.0f, 3.25f, 3.5f, 3.75f, 4.0f, 4.25f, 4.5f, 4.5f, 4.5f, 4.5f,
|
||||
4.0f, 4.25f, 4.5f, 4.75f, 5.0f, 5.25f, 5.5f, 5.75f, 6.0f, 6.0f, 6.0f, 6.0f,
|
||||
4.0f, 4.25f, 4.5f, 4.75f, 5.0f, 5.25f, 5.5f, 5.75f, 6.0f, 6.0f, 6.0f, 6.0f,
|
||||
|
||||
7.0f, 7.25f, 7.5f, 7.75f, 8.0f, 8.25f, 8.5f, 8.75f, 9.0f, 9.0f, 9.0f, 9.0f,
|
||||
8.5f, 8.75f, 9.0f, 9.25f, 9.5f, 9.75f, 10.0f, 10.25f, 10.5f, 10.5f, 10.5f, 10.5f,
|
||||
10.0f, 10.25f, 10.5f, 10.75f, 11.0f, 11.25f, 11.5f, 11.75f, 12.0f, 12.0f, 12.0f, 12.0f,
|
||||
10.0f, 10.25f, 10.5f, 10.75f, 11.0f, 11.25f, 11.5f, 11.75f, 12.0f, 12.0f, 12.0f, 12.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOp4DBilinearTest) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 2.0f, 1.0f};
|
||||
test.AddAttribute("mode", "linear");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 2, H = 2, W = 2, C = 3;
|
||||
std::vector<float> X = {1.0f, 2.0f, 3.0f,
|
||||
4.0f, 5.0f, 6.0f,
|
||||
7.0f, 8.0f, 9.0f,
|
||||
10.0f, 11.0f, 12.0f,
|
||||
|
||||
13.0f, 14.0f, 15.0f,
|
||||
16.0f, 17.0f, 18.0f,
|
||||
19.0f, 20.0f, 21.0f,
|
||||
22.0f, 23.0f, 24.0f};
|
||||
|
||||
test.AddInput<float>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<float> Y = {
|
||||
1.0f, 2.0f, 3.0f,
|
||||
2.5f, 3.5f, 4.5f,
|
||||
4.0f, 5.0f, 6.0f,
|
||||
4.0f, 5.0f, 6.0f,
|
||||
|
||||
4.0f, 5.0f, 6.0f,
|
||||
5.5f, 6.5f, 7.5f,
|
||||
7.0f, 8.0f, 9.0f,
|
||||
7.0f, 8.0f, 9.0f,
|
||||
|
||||
7.0f, 8.0f, 9.0f,
|
||||
8.5f, 9.5f, 10.5f,
|
||||
10.0f, 11.0f, 12.0f,
|
||||
10.0f, 11.0f, 12.0f,
|
||||
|
||||
7.0f, 8.0f, 9.0f,
|
||||
8.5f, 9.5f, 10.5f,
|
||||
10.0f, 11.0f, 12.0f,
|
||||
10.0f, 11.0f, 12.0f,
|
||||
|
||||
13.0f, 14.0f, 15.0f,
|
||||
14.5f, 15.5f, 16.5f,
|
||||
16.0f, 17.0f, 18.0f,
|
||||
16.0f, 17.0f, 18.0f,
|
||||
|
||||
16.0f, 17.0f, 18.0f,
|
||||
17.5f, 18.5f, 19.5f,
|
||||
19.0f, 20.0f, 21.0f,
|
||||
19.0f, 20.0f, 21.0f,
|
||||
|
||||
19.0f, 20.0f, 21.0f,
|
||||
20.5f, 21.5f, 22.5f,
|
||||
22.0f, 23.0f, 24.0f,
|
||||
22.0f, 23.0f, 24.0f,
|
||||
|
||||
19.0f, 20.0f, 21.0f,
|
||||
20.5f, 21.5f, 22.5f,
|
||||
22.0f, 23.0f, 24.0f,
|
||||
22.0f, 23.0f, 24.0f};
|
||||
|
||||
test.AddOutput<float>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOp2DBilinearTest) {
|
||||
|
|
@ -375,6 +834,41 @@ TEST(UpsampleOpTest, UpsampleOp4DBilinearTest_int32) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOp4DBilinearTest_int32) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 4.0f, 1.0f};
|
||||
test.AddAttribute("mode", "linear");
|
||||
test.AddAttribute("scales", scales);
|
||||
|
||||
constexpr int64_t N = 2, H = 2, W = 2, C = 1;
|
||||
std::vector<int32_t> X = {1, 3,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
7, 9};
|
||||
|
||||
test.AddInput<int32_t>("X", {N, H, W, C}, X);
|
||||
|
||||
std::vector<int32_t> Y = {
|
||||
1, 1, 2, 2, 3, 3, 3, 3,
|
||||
2, 2, 3, 3, 4, 4, 4, 4,
|
||||
3, 3, 4, 4, 5, 5, 5, 5,
|
||||
3, 3, 4, 4, 5, 5, 5, 5,
|
||||
|
||||
3, 3, 4, 4, 5, 5, 5, 5,
|
||||
5, 5, 6, 6, 7, 7, 7, 7,
|
||||
7, 7, 8, 8, 9, 9, 9, 9,
|
||||
7, 7, 8, 8, 9, 9, 9, 9};
|
||||
|
||||
test.AddOutput<int32_t>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, UpsampleOpNearestTest_1D) {
|
||||
OpTester test("Upsample");
|
||||
|
||||
|
|
@ -427,5 +921,50 @@ TEST(UpsampleOpTest, UpsampleOpNearest2XTest_opset9) {
|
|||
test.AddOutput<int32_t>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
|
||||
test.Run();
|
||||
}
|
||||
|
||||
TEST(UpsampleOpTest, NhwcUpsampleOpNearest2XTest_opset9) {
|
||||
OpTester test("Upsample", 9);
|
||||
|
||||
std::vector<float> scales{1.0f, 2.0f, 2.0f, 1.0};
|
||||
test.AddAttribute("mode", "nearest");
|
||||
|
||||
constexpr int64_t N = 1, H = 2, W = 2, C = 2;
|
||||
std::vector<int32_t> X = {1, 3,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
7, 9};
|
||||
|
||||
test.AddInput<int32_t>("X", {N, H, W, C}, X);
|
||||
test.AddInput<float>("scales", {4}, scales);
|
||||
|
||||
std::vector<int32_t> Y = {
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
1, 3,
|
||||
1, 3,
|
||||
3, 5,
|
||||
3, 5,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9,
|
||||
|
||||
3, 5,
|
||||
3, 5,
|
||||
7, 9,
|
||||
7, 9};
|
||||
|
||||
test.AddOutput<int32_t>("Y", {N, (int64_t)(H * scales[1]), (int64_t)(W * scales[2]), C}, Y);
|
||||
//CUDA: result mismatch due to not implementing NHWC support
|
||||
//TensorRT: results mismatch
|
||||
//ROCm: results mismatch
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "",
|
||||
{kCudaExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider});
|
||||
}
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
Loading…
Reference in a new issue