relayout.cpp 6.0 KB
Newer Older
1 2 3 4
/**
 * \file dnn/test/common/relayout.cpp
 * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
 *
5
 * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
6 7 8 9 10 11 12 13 14 15 16
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

#include "megdnn/oprs/general.h"

#include "src/common/relayout_helper.h"
#include "test/common/benchmarker.h"
#include "test/common/checker.h"
M
Megvii Engine Team 已提交
17
#include "test/common/relayout.h"
18 19 20 21 22 23 24

using namespace megdnn;
using namespace test;
using namespace megdnn::relayout;
using namespace test::relayout;

namespace {
M
Megvii Engine Team 已提交
25 26
TestArg generate_transpose_args(
        size_t batch, size_t m, size_t n, size_t c, DType dtype) {
27 28
    TestArg arg;
    arg.src = TensorLayout(
M
Megvii Engine Team 已提交
29 30 31 32
            TensorShape{batch, n, m, c},
            {static_cast<std::ptrdiff_t>(n * m * c), static_cast<std::ptrdiff_t>(c),
             static_cast<std::ptrdiff_t>(n * c), 1},
            dtype);
33 34 35
    arg.dst = TensorLayout(TensorShape{batch, n, m, c}, dtype);
    return arg;
}
M
Megvii Engine Team 已提交
36
}  // anonymous namespace
37 38 39 40 41

namespace megdnn {
namespace test {
namespace relayout {

42
void run_test_cv(Handle* handle, size_t CH) {
43 44 45 46
    std::vector<TestArg> args;

    for (size_t M = 124; M <= 130; ++M) {
        for (size_t N = 124; N <= 130; ++N) {
M
Megvii Engine Team 已提交
47 48 49 50
            args.push_back(generate_transpose_args(1, M, N, CH, dtype::Uint8()));
            args.push_back(generate_transpose_args(1, M, N, CH, dtype::Int32()));
            args.push_back(generate_transpose_args(1, M, N, CH, dtype::Float32()));
            args.push_back(generate_transpose_args(3, M, N, CH, dtype::Float32()));
51 52 53 54 55
        }
    }

    Checker<Relayout> checker(handle);

56
    for (auto&& arg : args) {
57 58 59 60
        checker.execl({arg.src, arg.dst});
    }
}

61
#define DEF_TEST(name) \
M
Megvii Engine Team 已提交
62 63
    template <>        \
    void run_test<name>(Handle * handle)
64 65 66 67 68 69 70 71 72 73 74 75

DEF_TEST(cv) {
    run_test_cv(handle, 1);
}

DEF_TEST(cv_ch3) {
    run_test_cv(handle, 3);
}

DEF_TEST(cv_ch5) {
    run_test_cv(handle, 5);
}
76 77 78

DEF_TEST(broadcast) {
    std::vector<TestArg> args;
M
Megvii Engine Team 已提交
79
    TensorLayout src{{2, 3, 4}, dtype::Float32()}, dst{{2, 3, 4}, dtype::Float32()};
80 81 82 83 84 85

    src.stride[0] = 4;
    src.stride[1] = 0;
    args.emplace_back(src, dst);

    // last stride contiguous
M
Megvii Engine Team 已提交
86 87 88
    args.emplace_back(
            TensorLayout({3, 100, 2}, {2, 0, 1}, dtype::Float16()),
            TensorLayout({3, 100, 2}, {200, 2, 1}, dtype::Float16()));
89 90
    Checker<Relayout> checker(handle);

M
Megvii Engine Team 已提交
91
    for (auto&& arg : args) {
92 93 94 95 96
        checker.execl({arg.src, arg.dst});
    }
}

DEF_TEST(negative) {
M
Megvii Engine Team 已提交
97
    TensorLayout src{{7, 8, 10}, dtype::Float32()}, dst{{7, 8, 10}, dtype::Float32()};
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

    src.stride[0] *= -1;

    Checker<Relayout> checker(handle);
    checker.execl({src, dst});
}

DEF_TEST(transpose) {
    Checker<Relayout> checker(handle);
    {
        TensorLayout sl({8, 10}, dtype::Int32()), dl({10, 8}, dtype::Int32());
        sl = sl.dimshuffle({1, 0});
        checker.execl({sl, dl});
        checker.execl({dl, sl});
    }
    {
M
Megvii Engine Team 已提交
114
        TensorLayout sl({8, 10, 2}, dtype::Int32()), dl({2, 8, 10}, dtype::Int32());
115 116 117 118 119 120 121 122
        sl = sl.dimshuffle({2, 0, 1});
        checker.execl({sl, dl});
        checker.execl({dl, sl});
    }
}

#undef DEF_TEST

M
Megvii Engine Team 已提交
123 124 125
}  // namespace relayout
}  // namespace test
}  // namespace megdnn
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

void test::relayout::run_cv_benchmark(Handle* handle) {
    auto handle_naive = create_cpu_handle(2);
    std::vector<TestArg> args;

    args.push_back(generate_transpose_args(1, 255, 256, 1, dtype::Int32()));
    args.push_back(generate_transpose_args(1, 513, 1025, 3, dtype::Int32()));

    args.push_back(generate_transpose_args(1, 255, 256, 1, dtype::Uint8()));
    args.push_back(generate_transpose_args(1, 513, 1025, 3, dtype::Uint8()));

    args.push_back(generate_transpose_args(1, 255, 256, 3, dtype::Float32()));
    args.push_back(generate_transpose_args(1, 513, 1025, 1, dtype::Float32()));

    args.push_back(generate_transpose_args(2, 987, 573, 6, dtype::Float32()));

    Benchmarker<Relayout> benchmarker(handle);
    Benchmarker<Relayout> benchmarker_naive(handle_naive.get());

    Checker<Relayout> checker(handle);
    benchmarker_naive.set_times(1).set_display(false);
    benchmarker.set_times(1).set_display(false);
    for (auto&& arg : args) {
        checker.execl({arg.src, arg.dst});
        auto t0 = benchmarker.execl({arg.src, arg.dst});
        auto t1 = benchmarker_naive.execl({arg.src, arg.dst});
        double k = arg.dst.span().dist_byte() * 1e3 / (1024 * 1024 * 1024);
M
Megvii Engine Team 已提交
153 154
        printf("cur=%7.3fms,%5.2fGiB/s naive=%7.3fms,%5.2fGiB/s %s %s\n", t0, k / t0,
               t1, k / t1, arg.dst.TensorShape::to_string().c_str(),
155 156 157 158
               arg.dst.dtype.name());
    }
}
TEST(RELAYOUT, TRANSPOSE_DET) {
M
Megvii Engine Team 已提交
159
    auto run = [](const TensorShape& shape, const std::vector<size_t>& dimshuffle,
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
                  bool expect_is_transpose, const TransposeParam& p = {}) {
        TensorLayout src{shape, dtype::Float32{}};
        src = src.dimshuffle(dimshuffle).collapse_contiguous();
        TensorLayout dst{TensorShape{src.total_nr_elems()}, src.dtype};
        TransposeParam p_get;
        bool succ = is_transpose(src, dst, p_get);
        ASSERT_EQ(expect_is_transpose, succ);
        if (succ) {
            ASSERT_EQ(p_get.batch, p.batch);
            ASSERT_EQ(p_get.m, p.m);
            ASSERT_EQ(p_get.n, p.n);
            ASSERT_EQ(p_get.c, p.c);
        }
        // swap m, n
        succ = is_transpose(dst, src, p_get);
        ASSERT_EQ(expect_is_transpose, succ);
        if (succ) {
            ASSERT_EQ(p_get.batch, p.batch);
            ASSERT_EQ(p_get.m, p.n);
            ASSERT_EQ(p_get.n, p.m);
            ASSERT_EQ(p_get.c, p.c);
        }
    };
183 184 185 186 187
    run({2, 3}, {1, 0}, true, {1, 2, 3, 1, 0});
    run({2, 3, 5}, {1, 0, 2}, true, {1, 2, 3, 5, 0});
    run({2, 3, 5}, {0, 2, 1}, true, {2, 3, 5, 1, 0});
    run({3, 2, 3, 5}, {0, 2, 1, 3}, true, {3, 2, 3, 5, 0});
    run({3, 2, 3, 5}, {0, 1, 3, 2}, true, {6, 3, 5, 1, 0});
188 189 190 191
    run({2, 3, 5}, {2, 1, 0}, false);
    run({3, 2, 3, 5}, {3, 2, 1, 0}, false);
}
// vim: syntax=cpp.doxygen