blob: 3a86db745c9c8748eb364bc69329a6251af2c59d [file] [edit]
// clang-format off
// Copyright 2023 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
#include <algorithm>
#include <limits>
#include <string>
#include <gtest/gtest.h>
#include "replicable_random_device.h"
#include "xnnpack.h"
#include "src/xnnpack/buffer.h"
#include "src/xnnpack/common.h"
#include "src/xnnpack/conv.h"
#include "src/xnnpack/isa-checks.h"
#include "src/xnnpack/microfnptr.h"
#include "src/xnnpack/microparams-init.h"
#include "src/xnnpack/microparams.h"
#include "src/xnnpack/pack.h"
#include "test/conv-hwc-microkernel-tester.h"
namespace {
struct XnnTestParam {
const char *name;
ConvHWCMicrokernelTester::Kernel kernel;
uint64_t arch_flags;
size_t kernel_size, subsampling, padding_right, padding_left, input_channels, output_channels_tile, input_widths;
};
class XnnTest : public testing::TestWithParam<XnnTestParam> {};
std::string GetTestName(const testing::TestParamInfo<XnnTest::ParamType>& info) {
return info.param.name;
}
#define XNN_UKERNEL(arch_flags, ukernel, kernel_size, subsampling, padding_right, padding_left, input_channels, output_channels_tile, input_widths, datatype, params_type, init_params) \
{ #ukernel, ConvHWCMicrokernelTester::Kernel{ukernel, init_params}, arch_flags, kernel_size, subsampling, padding_right, padding_left, input_channels, output_channels_tile, input_widths },
const XnnTestParam xnn_test_params[] = {
#include "src/f32-conv-hwc/f32-conv-hwc.inc"
};
TEST_P(XnnTest, input_width_eq)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(GetParam().output_channels_tile)
.input_width(GetParam().input_widths)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
TEST_P(XnnTest, input_width_div)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
if (GetParam().input_widths <= 1) {
GTEST_SKIP();
}
for (size_t input_width = GetParam().input_widths * 2; input_width < (GetParam().input_widths * 8);
input_width += GetParam().input_widths * 3) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(GetParam().output_channels_tile)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
TEST_P(XnnTest, input_width_lt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t input_width = (GetParam().padding_left ? 1 : 2); input_width < GetParam().input_widths; input_width++) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(GetParam().output_channels_tile)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
TEST_P(XnnTest, input_width_gt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t input_width = GetParam().input_widths + 1; input_width < GetParam().input_widths * 2; input_width++) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(GetParam().output_channels_tile)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
TEST_P(XnnTest, output_channels_lt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile; output_channels++) {
for (size_t input_width = (GetParam().padding_left ? 1 : 2); input_width < GetParam().input_widths * 8;
input_width += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
TEST_P(XnnTest, output_channels_div)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_channels = GetParam().output_channels_tile * 2;
output_channels <= GetParam().output_channels_tile * 4; output_channels += GetParam().output_channels_tile) {
for (size_t input_width = (GetParam().padding_left ? 1 : 2); input_width < GetParam().input_widths * 8;
input_width += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
TEST_P(XnnTest, output_channels_gt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_channels = GetParam().output_channels_tile + 1;
output_channels < GetParam().output_channels_tile * 2; output_channels++) {
for (size_t input_width = (GetParam().padding_left ? 1 : 2); input_width < GetParam().input_widths * 8;
input_width += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_width)
.input_height(GetParam().kernel_size)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
TEST_P(XnnTest, input_height_lt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t input_heights = 1; input_heights < 3; input_heights++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
auto tester = ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(input_heights);
if (GetParam().padding_left == 0) {
tester.padding_right(1);
tester.padding_height(1);
} else {
tester.padding(1);
}
tester.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, input_height_gt)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t input_heights = 4; input_heights <= 9; input_heights++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(input_heights)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, padding_top)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t padding_tops = 0; padding_tops <= 1; padding_tops++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(9)
.padding(GetParam().padding_left, GetParam().padding_right)
.padding_top(padding_tops)
.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, padding_bottom)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t padding_bottoms = 0; padding_bottoms <= 1; padding_bottoms++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(9)
.padding(GetParam().padding_left, GetParam().padding_right)
.padding_bottom(padding_bottoms)
.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, output_y_start)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_y_starts = 1; output_y_starts <= 3; output_y_starts++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(9)
.output_y_start(output_y_starts)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, output_y_end)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_y_ends = 2; output_y_ends < 5; output_y_ends++) {
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(9)
.output_y_end(output_y_ends)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
}
TEST_P(XnnTest, qmin)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(6)
.qmin(128)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
TEST_P(XnnTest, qmax)
{
TEST_REQUIRES_ARCH_FLAGS(GetParam().arch_flags);
for (size_t output_channels = 1; output_channels < GetParam().output_channels_tile * 2;
output_channels += GetParam().output_channels_tile - 1) {
for (size_t input_widths_ = (GetParam().padding_left ? 1 : 2); input_widths_ < GetParam().input_widths * 8;
input_widths_ += (GetParam().input_widths * 2 - 1)) {
ConvHWCMicrokernelTester()
.kernel_size(GetParam().kernel_size)
.subsampling(GetParam().subsampling)
.input_channels(GetParam().input_channels)
.output_channels_tile(GetParam().output_channels_tile)
.output_channels(output_channels)
.input_width(input_widths_)
.input_height(6)
.qmax(128)
.padding(GetParam().padding_left, GetParam().padding_right)
.Test(GetParam().kernel);
}
}
}
INSTANTIATE_TEST_SUITE_P(conv_hwc,
XnnTest,
testing::ValuesIn(xnn_test_params),
GetTestName);
} // namespace