profiler.py 16.9 KB
Newer Older
1
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
D
dzhwinter 已提交
2
#
D
dzhwinter 已提交
3 4 5
# 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
D
dzhwinter 已提交
6
#
D
dzhwinter 已提交
7
#     http://www.apache.org/licenses/LICENSE-2.0
D
dzhwinter 已提交
8
#
D
dzhwinter 已提交
9 10 11 12 13 14
# 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.

15 16
from __future__ import print_function

17
from . import core
S
rename  
sneaxiy 已提交
18
from .wrapped_decorator import signature_safe_contextmanager
19
import os
M
minqiyang 已提交
20
import six
L
Leo Chen 已提交
21
import sys
D
dangqingqing 已提交
22

C
chenjian 已提交
23 24
from paddle.utils.deprecated import deprecated

X
Xin Pan 已提交
25 26 27 28
__all__ = [
    'cuda_profiler', 'reset_profiler', 'profiler', 'start_profiler',
    'stop_profiler'
]
D
dangqingqing 已提交
29

D
dangqingqing 已提交
30
NVPROF_CONFIG = [
31 32 33 34 35 36
    "gpustarttimestamp",
    "gpuendtimestamp",
    "gridsize3d",
    "threadblocksize",
    "streamid",
    "enableonstart 0",
D
dangqingqing 已提交
37
    "conckerneltrace",
38 39 40
]


C
chenjian 已提交
41 42 43 44 45 46
@deprecated(
    since="2.3.0",
    update_to="paddle.profiler.Profiler",
    level=1,
    reason="Please use new profiler tool, this profiler tool is no longer maintained."
)
S
rename  
sneaxiy 已提交
47
@signature_safe_contextmanager
D
dangqingqing 已提交
48
def cuda_profiler(output_file, output_mode=None, config=None):
T
Tao Luo 已提交
49
    """
C
chenjian 已提交
50
    API cuda_profiler has been abandoned. If you have relevant requirements, you can use `paddle.utils.profiler.start_profiler` and `paddle.utils.profiler.stop_profiler`.
51 52 53 54
    The relevant reference documents are as follows:
    <https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/utils/profiler/start_profiler_en.html#start-profiler>
    <https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/utils/profiler/stop_profiler_en.html#stop-profiler>
    <https://www.paddlepaddle.org.cn/documentation/docs/en/advanced_guide/performance_improving/analysis_tools/timeline_en.html>
D
dangqingqing 已提交
55
    """
56 57 58
    raise RuntimeError(
        "API cuda_profiler has been abandoned. If you have relevant requirements, you can use `paddle.utils.profiler.start_profiler` and `paddle.utils.profiler.stop_profiler`.\nThe relevant reference documents are as follows:\n<https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/utils/profiler/start_profiler_en.html#start-profiler>\n<https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/utils/profiler/stop_profiler_en.html#stop-profiler>\n<https://www.paddlepaddle.org.cn/documentation/docs/en/advanced_guide/performance_improving/analysis_tools/timeline_en.html>"
    )
59 60


61 62 63 64
@signature_safe_contextmanager
def npu_profiler(output_file, config=None):
    """
    The NPU profiler.
C
chenjian 已提交
65

66 67
    This fuctions is used to profile NPU program by NPU runtime application
    programming interface. The profiling result will be written into
C
chenjian 已提交
68 69 70 71
    `output_file`. The users can set set the NPU profiling config by `config` argument.

    After getting the profiling result file, users can use
    `tools provided by Ascend <https://support.huaweicloud.com/tg-Inference-cann/atlasprofiling_16_0006.html>`_
72 73 74 75
    to load this output file to visualize results.

    Args:
        output_file (str) : The output file name, the result will be
C
chenjian 已提交
76
            written into this file. It should be absolute path.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
        config (list<str>, optional) : NPU profile config. For more details, please
            refer to `User Guide <https://support.huaweicloud.com/tg-Inference-cann/atlasprofiling_16_0006.html>`_ .

    Examples:

        .. code-block:: python

            import paddle.fluid as fluid
            import paddle.fluid.profiler as profiler
            import numpy as np

            epoc = 8
            dshape = [4, 3, 28, 28]
            data = fluid.data(name='data', shape=[None, 3, 28, 28], dtype='float32')
            conv = fluid.layers.conv2d(data, 20, 3, stride=[1, 1], padding=[1, 1])

            place = fluid.NPUPlace(0)
            exe = fluid.Executor(place)
            exe.run(fluid.default_startup_program())

            output_file = 'npu.txt'
            with profiler.npu_profiler(output_file) as npu_prof:
                for i in range(epoc):
                    input = np.random.random(dshape).astype('float32')
                    exe.run(fluid.default_main_program(), feed={'data': input})
            # then use  NPU profiler tools to load this output file
            # to visualize results.
    """
    # TODO: support config in python.
    if not config:
        config = core.npu_prof_create_config()

    core.npu_prof_init(output_file)
    # Enables profiler collection by the active NPU profiling tool.
    core.npu_prof_start(config)
    try:
        yield
    # Disables profiler collection.
    finally:
        core.npu_prof_stop(config)
        core.npu_prof_finalize()


C
chenjian 已提交
120 121 122 123 124 125
@deprecated(
    since="2.3.0",
    update_to="paddle.profiler.Profiler",
    level=1,
    reason="Please use new profiler tool, this profiler tool is no longer maintained."
)
126
def reset_profiler():
D
Dang Qingqing 已提交
127
    """
128
    Clear the previous time record. It works for
D
Dang Qingqing 已提交
129 130 131 132 133 134 135
    `fluid.profiler.start_profiler`, `fluid.profiler.stop_profiler`,
    and `fluid.profiler.profiler`.

    Examples:

        .. code-block:: python

136
            # required: gpu
137
            import paddle.fluid as fluid
D
Dang Qingqing 已提交
138
            import paddle.fluid.profiler as profiler
139
            with profiler.profiler('CPU', 'total', '/tmp/profile'):
D
Dang Qingqing 已提交
140 141 142 143
                for iter in range(10):
                    if iter == 2:
                        profiler.reset_profiler()
                    # ...
144
    """
145 146 147
    core.reset_profiler()


C
chenjian 已提交
148 149 150 151 152 153
@deprecated(
    since="2.3.0",
    update_to="paddle.profiler.Profiler",
    level=1,
    reason="Please use new profiler tool, this profiler tool is no longer maintained."
)
154
def start_profiler(state, tracer_option='Default'):
D
Dang Qingqing 已提交
155 156
    """
    Enable the profiler. Uers can use `fluid.profiler.start_profiler` and
C
chenjian 已提交
157
    `fluid.profiler.stop_profiler` to profile, which is equal to the usage
T
Tao Luo 已提交
158
    of `fluid.profiler.profiler` interface.
X
Xin Pan 已提交
159 160

    Args:
T
Tao Luo 已提交
161 162
        state (str) : The profiling state, which should be one of 'CPU', 'GPU'
            or 'All'. 'CPU' means only profiling CPU; 'GPU' means profiling
C
chenjian 已提交
163
            both CPU and GPU; 'All' means profiling both CPU and GPU, and
T
Tao Luo 已提交
164
            generates timeline as well.
W
wangchaochaohu 已提交
165
        tracer_option (str, optional) : tracer_option can be one of ['Default', 'OpDetail', 'AllOpDetail'], it
C
chenjian 已提交
166 167 168
            can control the profile level and print the different level profile result. `Default` option print
            the different Op type profiling result and the `OpDetail` option print the detail profiling
            result of different op types such as compute and data transform, `AllOpDetail` option
W
wangchaochaohu 已提交
169
            print the detail profiling result of different op name same as `OpDetail`.
D
Dang Qingqing 已提交
170 171

    Raises:
C
chenjian 已提交
172
        ValueError: If `state` is not in ['CPU', 'GPU', 'All'] or `tracer_option`
W
wangchaochaohu 已提交
173
            is not in ['Default', 'OpDetail', 'AllOpDetail'].
D
Dang Qingqing 已提交
174 175 176 177 178

    Examples:

        .. code-block:: python

C
chenjian 已提交
179
            # required: gpu
180
            import paddle.fluid as fluid
D
Dang Qingqing 已提交
181 182 183 184 185 186 187 188
            import paddle.fluid.profiler as profiler

            profiler.start_profiler('GPU')
            for iter in range(10):
                if iter == 2:
                    profiler.reset_profiler()
                # except each iteration
            profiler.stop_profiler('total', '/tmp/profile')
C
chenjian 已提交
189

190 191 192 193 194 195
            profiler.start_profiler('GPU', "OpDetail")
            for iter in range(10):
                if iter == 2:
                    profiler.reset_profiler()
                # except each iteration
            profiler.stop_profiler('total', '/tmp/profile')
X
Xin Pan 已提交
196 197 198
    """
    if core.is_profiler_enabled():
        return
X
Xin Pan 已提交
199 200 201 202 203 204 205 206
    if state not in ['CPU', 'GPU', "All"]:
        raise ValueError("The state must be 'CPU' or 'GPU' or 'All'.")
    if state == "GPU":
        prof_state = core.ProfilerState.kCUDA
    elif state == "CPU":
        prof_state = core.ProfilerState.kCPU
    else:
        prof_state = core.ProfilerState.kAll
207 208 209 210 211 212 213 214 215 216 217 218

    if tracer_option not in ['Default', 'OpDetail', 'AllOpDetail']:
        raise ValueError(
            "tracer option must be 'Default', 'OpDetail', 'AllOpDetail'.")
    if tracer_option == "Default":
        prof_tracer_option = core.TracerOption.kDefault
    elif tracer_option == "OpDetail":
        prof_tracer_option = core.TracerOption.kOpDetail
    else:
        prof_tracer_option = core.TracerOption.kAllOpDetail

    core.set_tracer_option(prof_tracer_option)
X
Xin Pan 已提交
219 220 221
    core.enable_profiler(prof_state)


C
chenjian 已提交
222 223 224 225 226 227
@deprecated(
    since="2.3.0",
    update_to="paddle.profiler.Profiler",
    level=1,
    reason="Please use new profiler tool, this profiler tool is no longer maintained."
)
X
Xin Pan 已提交
228
def stop_profiler(sorted_key=None, profile_path='/tmp/profile'):
D
Dang Qingqing 已提交
229 230
    """
    Stop the profiler. Uers can use `fluid.profiler.start_profiler` and
C
chenjian 已提交
231
    `fluid.profiler.stop_profiler` to profile, which is equal to the usage
T
Tao Luo 已提交
232
    of `fluid.profiler.profiler` interface.
X
Xin Pan 已提交
233 234

    Args:
C
chenjian 已提交
235
        sorted_key (str, optional) : The order of profiling results, which
T
Tao Luo 已提交
236 237 238
            should be one of None, 'calls', 'total', 'max', 'min' or 'ave'.
            Default is None, means the profiling results will be printed
            in the order of first end time of events.
X
Xin Pan 已提交
239 240 241 242 243
            The `calls` means sorting by the number of calls.
            The `total` means sorting by the total execution time.
            The `max` means sorting by the maximum execution time.
            The `min` means sorting by the minimum execution time.
            The `ave` means sorting by the average execution time.
C
chenjian 已提交
244
            and write it into `profile_path`. The default profile_path is `/tmp/profile`.
245
        profile_path (str, optional) : If state == 'All', it will generate timeline,
D
Dang Qingqing 已提交
246 247 248 249 250 251 252 253 254

    Raises:
        ValueError: If `sorted_key` is not in
            ['calls', 'total', 'max', 'min', 'ave'].

    Examples:

        .. code-block:: python

C
chenjian 已提交
255
            # required: gpu
256
            import paddle.fluid as fluid
D
Dang Qingqing 已提交
257 258 259 260 261 262 263 264
            import paddle.fluid.profiler as profiler

            profiler.start_profiler('GPU')
            for iter in range(10):
                if iter == 2:
                    profiler.reset_profiler()
                # except each iteration
            profiler.stop_profiler('total', '/tmp/profile')
X
Xin Pan 已提交
265 266 267
    """
    if not core.is_profiler_enabled():
        return
X
Xin Pan 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    sorted_key = 'default' if sorted_key is None else sorted_key
    if sorted_key not in ['default', 'calls', 'total', 'max', 'min', 'ave']:
        raise ValueError("The sorted_key must be None or in 'calls', 'total', "
                         "'max', 'min' and 'ave'")
    key_map = {
        'default': core.EventSortingKey.kDefault,
        'calls': core.EventSortingKey.kCalls,
        'total': core.EventSortingKey.kTotal,
        'max': core.EventSortingKey.kMax,
        'min': core.EventSortingKey.kMin,
        'ave': core.EventSortingKey.kAve,
    }
    # TODO(qingqing) : redirect C++ ostream to Python stream.
    # with core.ostream_redirect(stdout=True, stderr=True):
    core.disable_profiler(key_map[sorted_key], profile_path)


C
chenjian 已提交
285 286 287 288 289 290
@deprecated(
    since="2.3.0",
    update_to="paddle.profiler.Profiler",
    level=1,
    reason="Please use new profiler tool, this profiler tool is no longer maintained."
)
S
rename  
sneaxiy 已提交
291
@signature_safe_contextmanager
292 293 294 295
def profiler(state,
             sorted_key=None,
             profile_path='/tmp/profile',
             tracer_option='Default'):
T
Tao Luo 已提交
296
    """
297
    The profiler interface. This profiler can be used to profile both CPU and GPU program.
298 299

    Args:
T
Tao Luo 已提交
300 301
        state (str) : The profiling state, which should be one of 'CPU', 'GPU'
            or 'All'. 'CPU' means only profiling CPU; 'GPU' means profiling
C
chenjian 已提交
302
            both CPU and GPU; 'All' means profiling both CPU and GPU, and
T
Tao Luo 已提交
303
            generates timeline as well.
C
chenjian 已提交
304
        sorted_key (str, optional) : The order of profiling results, which
T
Tao Luo 已提交
305 306 307
            should be one of None, 'calls', 'total', 'max', 'min' or 'ave'.
            Default is None, means the profiling results will be printed
            in the order of first end time of events.
308
            The `calls` means sorting by the number of calls.
309 310 311 312
            The `total` means sorting by the total execution time.
            The `max` means sorting by the maximum execution time.
            The `min` means sorting by the minimum execution time.
            The `ave` means sorting by the average execution time.
T
Tao Luo 已提交
313
        profile_path (str, optional) : If state == 'All', it will generate timeline,
C
chenjian 已提交
314
            and write it into `profile_path`. The default profile_path is `/tmp/profile`.
W
wangchaochaohu 已提交
315
        tracer_option (str, optional) : tracer_option can be one of ['Default', 'OpDetail', 'AllOpDetail'], it
C
chenjian 已提交
316 317 318
            can control the profile level and print the different level profile result. `Default` option print
            the different Op type profiling result and the `OpDetail` option print the detail profiling
            result of different op types such as compute and data transform, `AllOpDetail` option
W
wangchaochaohu 已提交
319
            print the detail profiling result of different op name same as `OpDetail`.
D
Dang Qingqing 已提交
320 321 322 323 324 325 326 327 328

    Raises:
        ValueError: If `state` is not in ['CPU', 'GPU', 'All']. If `sorted_key` is
            not in ['calls', 'total', 'max', 'min', 'ave'].

    Examples:

        .. code-block:: python

329
            # required: gpu
330
            import paddle.fluid as fluid
D
Dang Qingqing 已提交
331
            import paddle.fluid.profiler as profiler
332
            import numpy as np
333 334
            import paddle
            paddle.enable_static()
D
Dang Qingqing 已提交
335

336 337
            epoc = 8
            dshape = [4, 3, 28, 28]
T
Tao Luo 已提交
338
            data = fluid.data(name='data', shape=[None, 3, 28, 28], dtype='float32')
339 340 341 342 343 344
            conv = fluid.layers.conv2d(data, 20, 3, stride=[1, 1], padding=[1, 1])

            place = fluid.CPUPlace()
            exe = fluid.Executor(place)
            exe.run(fluid.default_startup_program())

345
            with profiler.profiler('CPU', 'total', '/tmp/profile', 'Default') as prof:
346 347 348
                for i in range(epoc):
                    input = np.random.random(dshape).astype('float32')
                    exe.run(fluid.default_main_program(), feed={'data': input})
T
Tao Luo 已提交
349 350 351 352 353 354 355

    Examples Results:

        .. code-block:: text

            #### Examples Results ####
            #### 1) sorted_key = 'total', 'calls', 'max', 'min', 'ave' ####
C
chenjian 已提交
356
            # The only difference in 5 sorted_key results is the following sentence:
T
Tao Luo 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
            # "Sorted by number of xxx in descending order in the same thread."
            # The reason is that in this example, above 5 columns are already sorted.
            ------------------------->     Profiling Report     <-------------------------

            Place: CPU
            Time unit: ms
            Sorted by total time in descending order in the same thread
            #Sorted by number of calls in descending order in the same thread
            #Sorted by number of max in descending order in the same thread
            #Sorted by number of min in descending order in the same thread
            #Sorted by number of avg in descending order in the same thread

            Event                       Calls       Total       Min.        Max.        Ave.        Ratio.
            thread0::conv2d             8           129.406     0.304303    127.076     16.1758     0.983319
            thread0::elementwise_add    8           2.11865     0.193486    0.525592    0.264832    0.016099
            thread0::feed               8           0.076649    0.006834    0.024616    0.00958112  0.000582432

            #### 2) sorted_key = None  ####
            # Since the profiling results are printed in the order of first end time of Ops,
C
chenjian 已提交
376
            # the printed order is feed->conv2d->elementwise_add
T
Tao Luo 已提交
377 378 379 380 381 382 383 384 385 386
            ------------------------->     Profiling Report     <-------------------------

            Place: CPU
            Time unit: ms
            Sorted by event first end time in descending order in the same thread

            Event                       Calls       Total       Min.        Max.        Ave.        Ratio.
            thread0::feed               8           0.077419    0.006608    0.023349    0.00967738  0.00775934
            thread0::conv2d             8           7.93456     0.291385    5.63342     0.99182     0.795243
            thread0::elementwise_add    8           1.96555     0.191884    0.518004    0.245693    0.196998
387
    """
388
    start_profiler(state, tracer_option)
389 390 391 392
    try:
        yield
    finally:
        stop_profiler(sorted_key, profile_path)
L
Leo Chen 已提交
393 394 395 396 397 398 399 400 401 402


@signature_safe_contextmanager
def _nvprof_range(iter_id, start, end, exit_after_prof=True):
    '''
    A range profiler interface (not public yet).

    Examples:

        .. code-block:: python
C
chenjian 已提交
403

L
Leo Chen 已提交
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
            model = Model()
            for i in range(max_iter):
                paddle.fluid.profiler._nvprof_range(i, 10, 20):
                    out = model(in)
    '''
    try:
        if iter_id == start:
            core.nvprof_start()
            core.nvprof_enable_record_event()
        if iter_id >= start:
            core.nvprof_nvtx_push(str(iter_id))
        yield
    finally:
        if iter_id < end:
            core.nvprof_nvtx_pop()
        if iter_id == end:
            core.nvprof_stop()
            if exit_after_prof:
                sys.exit()