quantization.cpp 2.93 KB
Newer Older
Shucai Xiao's avatar
Shucai Xiao committed
1
2
3
4
#include <migraphx/program.hpp>
#include <migraphx/quantization.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/instruction.hpp>
Shucai Xiao's avatar
Shucai Xiao committed
5
#include <migraphx/op/fp_conversion.hpp>
Shucai Xiao's avatar
Shucai Xiao committed
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <migraphx/target.hpp>
#include <migraphx/env.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/time.hpp>
#include <migraphx/iterator_for.hpp>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <utility>

namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {

19
instruction_ref convert_to_fp16(program& prog, instruction_ref& ins)
Shucai Xiao's avatar
Shucai Xiao committed
20
{
Shucai Xiao's avatar
Shucai Xiao committed
21
22
    assert(ins->get_shape().type() == shape::float_type ||
           ins->get_shape().type() == shape::double_type);
Shucai Xiao's avatar
Shucai Xiao committed
23
    assert(contains({"@literal", "@param"}, ins->name()));
Shucai Xiao's avatar
Shucai Xiao committed
24
25
26
    instruction_ref ins_fp16{};
    if(ins->name() == "@literal")
    {
Shucai Xiao's avatar
Shucai Xiao committed
27
28
29
        shape s = ins->get_shape();
        auto l  = ins->get_literal();
        if(s.type() == shape::float_type)
30
31
        {
            auto tv = l.get<const float>();
Shucai Xiao's avatar
Shucai Xiao committed
32
33
            ins_fp16 =
                prog.add_literal(literal({shape::half_type, s.lens()}, tv.begin(), tv.end()));
34
35
36
37
        }
        else
        {
            auto tv = l.get<const double>();
Shucai Xiao's avatar
Shucai Xiao committed
38
39
            ins_fp16 =
                prog.add_literal(literal({shape::half_type, s.lens()}, tv.begin(), tv.end()));
40
        }
Shucai Xiao's avatar
Shucai Xiao committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    }
    else if(ins->name() == "@param")
    {
        if(ins == std::prev(prog.end()))
        {
            ins_fp16 = prog.add_instruction(op::fp_conversion{}, ins);
        }
        else
        {
            ins_fp16 = prog.insert_instruction(std::next(ins), op::fp_conversion{}, ins);
        }
    }

    return ins_fp16;
}

void quantize(program& prog)
{
Shucai Xiao's avatar
Shucai Xiao committed
59
    bool reduced_precision  = false;
Shucai Xiao's avatar
Shucai Xiao committed
60
    shape::type_t orig_type = shape::float_type;
Shucai Xiao's avatar
Shucai Xiao committed
61
62
63
    for(auto ins : iterator_for(prog))
    {
        // convert float_type to half_type
Shucai Xiao's avatar
Shucai Xiao committed
64
65
        if(contains({"@literal", "@param"}, ins->name()) &&
           (ins->get_shape().type() == shape::float_type ||
Shucai Xiao's avatar
Shucai Xiao committed
66
            ins->get_shape().type() == shape::double_type))
Shucai Xiao's avatar
Shucai Xiao committed
67
        {
Shucai Xiao's avatar
Shucai Xiao committed
68
            orig_type     = ins->get_shape().type();
69
            auto ins_fp16 = convert_to_fp16(prog, ins);
Shucai Xiao's avatar
Shucai Xiao committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
            auto outputs  = ins->outputs();
            for(auto output : outputs)
            {
                if(output != ins_fp16)
                {
                    instruction::replace_argument(output, ins, ins_fp16, false);
                }
            }

            reduced_precision = true;
        }
    }

    // add another instruction at last to convert fp16 to fp32
    if(reduced_precision)
    {
        for(auto ins : iterator_for(prog))
        {
Shucai Xiao's avatar
Shucai Xiao committed
88
            if(!contains({"@literal", "@param"}, ins->name()))
Shucai Xiao's avatar
Shucai Xiao committed
89
90
91
92
93
94
95
96
            {
                ins->recompute_ins_shape();
            }
        }

        auto ins = std::prev(prog.end());
        if(ins->get_shape().type() == shape::half_type)
        {
Shucai Xiao's avatar
Shucai Xiao committed
97
            prog.add_instruction(op::fp_conversion{orig_type}, ins);
Shucai Xiao's avatar
Shucai Xiao committed
98
99
100
101
102
103
        }
    }
}

} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx