memory_usage_calc.py 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This module privides a memory usage calculate function for user.
The purpose of this API is to allow users to estimate memory usage of
M
minqiyang 已提交
17 18
a program under a special batch size, then user can set appropriate
batch size to fully utilize a GPU.
19 20 21 22

This API is still under active development and may change drastically.
"""

23 24
from __future__ import print_function

M
minqiyang 已提交
25 26
import six

27 28 29
from .. import core
from ..framework import Program, Variable

30
__all__ = ['memory_usage']
31 32 33 34 35 36 37 38 39 40 41 42

dtype_to_size = {
    core.VarDesc.VarType.FP16: 2,
    core.VarDesc.VarType.FP32: 4,
    core.VarDesc.VarType.FP64: 8,
    core.VarDesc.VarType.INT16: 2,
    core.VarDesc.VarType.INT32: 4,
    core.VarDesc.VarType.INT64: 8,
    core.VarDesc.VarType.BOOL: 1,
    core.VarDesc.VarType.UINT8: 1,
}

43
DEBUG = False
44 45


46 47 48
def memory_usage(program, batch_size):
    """
    Get the estimate memory usage of program with input batch size.
49

50 51
    Args:
        program(Program): The current Program.
M
minqiyang 已提交
52 53
        batch_size(int): The current input data batch_size.

54 55 56 57
    Returns:
        min_total_memory(float): the estimate memory usage lower bound.
        max_total_memory(float): the estimate memory usage upper bound.
        unit_str(string): the unit of estimate usage result.
M
minqiyang 已提交
58

59
    Examples:
M
minqiyang 已提交
60

61 62 63 64 65
        >>> import paddle.fluid as fluid
        >>> lower_usage, upper_usage, unit = fluid.contrib.memory_usage(
                fluid.default_main_program(), batch_size=10)
        >>> print "memory usage is about %.3f - %.3f %s" % \
                (lower_usage, upper_usage, unit)
66

67
    """
68

69 70 71 72
    # Parameters check
    if not isinstance(program, Program):
        raise TypeError(
            "Calculating Memory Usage requires Program as its Parameter."
F
fengjiayi 已提交
73
            "But you passed in %s" % (type(program)))
74 75
    if batch_size <= 0:
        raise ValueError("The batch size need to be positive.")
76

77 78
    # Get the var_name list of first block and calculate
    total_memory = 0.0
F
fengjiayi 已提交
79 80 81 82 83 84 85 86 87 88 89
    processed_var_names = set()
    for op in program.global_block().ops:
        for var_name in op.output_arg_names:
            if var_name in processed_var_names:
                continue
            processed_var_names.add(var_name)
            var = program.global_block().vars[var_name]
            if var.desc.type() != core.VarDesc.VarType.LOD_TENSOR:
                continue

            data_count = 1
F
update  
fengjiayi 已提交
90
            neg_dim_count = 0
F
fengjiayi 已提交
91 92
            for x in var.shape:
                if x < 0:
F
update  
fengjiayi 已提交
93 94 95 96
                    if neg_dim_count >= 1:
                        raise ValueError("Var %s has more than one negtive dim."
                                         % (var_name))
                    neg_dim_count += 1
F
fengjiayi 已提交
97 98 99 100 101 102 103
                    data_count *= batch_size * (-x)
                else:
                    data_count *= x
            var_memory = data_count * dtype_to_size[var.dtype]
            if DEBUG:
                print("%s memory usage: %d" % (var.name, var_memory))
            total_memory += var_memory
104
    if DEBUG:
M
minqiyang 已提交
105
        print("total memory usage: %.2f" % (total_memory))
106

107 108 109 110 111
    # Convert appropriate unit
    unit_str = "B"
    if total_memory > 1024:
        total_memory /= 1024
        unit_str = "KB"
112 113
        if total_memory > 1024:
            total_memory /= 1024
114
            unit_str = "MB"
115

116 117 118
    # Append extra memory consumption (5% - 10%)
    min_total_memory = total_memory * 1.05
    max_total_memory = total_memory * 1.1
119

120
    return min_total_memory, max_total_memory, unit_str