File size: 4,921 Bytes
079c32c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 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 120 121 122 123 124 125 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 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
import signal
import time
from typing import Any, Callable
import torch
from easydict import EasyDict
from .time_helper_base import TimeWrapper
from .time_helper_cuda import get_cuda_time_wrapper
def build_time_helper(cfg: EasyDict = None, wrapper_type: str = None) -> Callable[[], 'TimeWrapper']:
"""
Overview:
Build the timehelper
Arguments:
- cfg (:obj:`dict`):
The config file, which is a multilevel dict, have large domain like
evaluate, common, model, train etc, and each large domain
has it's smaller domain.
- wrapper_type (:obj:`str`): The type of wrapper returned, support ``['time', 'cuda']``
Returns:
- time_wrapper (:obj:`TimeWrapper`):
Return the corresponding timewrapper, Reference: ``ding.utils.timehelper.TimeWrapperTime``
and ``ding.utils.timehelper.get_cuda_time_wrapper``.
"""
# Note: wrapper_type has higher priority
if wrapper_type is not None:
time_wrapper_type = wrapper_type
elif cfg is not None:
time_wrapper_type = cfg.common.time_wrapper_type
else:
raise RuntimeError('Either wrapper_type or cfg should be provided.')
if time_wrapper_type == 'time':
return TimeWrapperTime
elif time_wrapper_type == 'cuda':
if torch.cuda.is_available():
# lazy initialize to make code runnable locally
return get_cuda_time_wrapper()
else:
return TimeWrapperTime
else:
raise KeyError('invalid time_wrapper_type: {}'.format(time_wrapper_type))
class EasyTimer:
"""
Overview:
A decent timer wrapper that can be used easily.
Interfaces:
``__init__``, ``__enter__``, ``__exit__``
Example:
>>> wait_timer = EasyTimer()
>>> with wait_timer:
>>> func(...)
>>> time_ = wait_timer.value # in second
"""
def __init__(self, cuda=True):
"""
Overview:
Init class EasyTimer
Arguments:
- cuda (:obj:`bool`): Whether to build timer with cuda type
"""
if torch.cuda.is_available() and cuda:
time_wrapper_type = "cuda"
else:
time_wrapper_type = "time"
self._timer = build_time_helper(wrapper_type=time_wrapper_type)
self.value = 0.0
def __enter__(self):
"""
Overview:
Enter timer, start timing
"""
self.value = 0.0
self._timer.start_time()
def __exit__(self, *args):
"""
Overview:
Exit timer, stop timing
"""
self.value = self._timer.end_time()
class TimeWrapperTime(TimeWrapper):
"""
Overview:
A class method that inherit from ``TimeWrapper`` class
Interfaces:
``start_time``, ``end_time``
"""
# overwrite
@classmethod
def start_time(cls):
"""
Overview:
Implement and override the ``start_time`` method in ``TimeWrapper`` class
"""
cls.start = time.time()
# overwrite
@classmethod
def end_time(cls):
"""
Overview:
Implement and override the end_time method in ``TimeWrapper`` class
Returns:
- time(:obj:`float`): The time between ``start_time`` and end_time
"""
cls.end = time.time()
return cls.end - cls.start
class WatchDog(object):
"""
Overview:
Simple watchdog timer to detect timeouts
Arguments:
- timeout (:obj:`int`): Timeout value of the ``watchdog [seconds]``.
.. note::
If it is not reset before exceeding this value, ``TimeourError`` raised.
Interfaces:
``start``, ``stop``
Examples:
>>> watchdog = WatchDog(x) # x is a timeout value
>>> ...
>>> watchdog.start()
>>> ... # Some function
"""
def __init__(self, timeout: int = 1):
"""
Overview:
Initialize watchdog with ``timeout`` value.
Arguments:
- timeout (:obj:`int`): Timeout value of the ``watchdog [seconds]``.
"""
self._timeout = timeout + 1
self._failed = False
def start(self):
"""
Overview:
Start watchdog.
"""
signal.signal(signal.SIGALRM, self._event)
signal.alarm(self._timeout)
@staticmethod
def _event(signum: Any, frame: Any):
"""
Overview:
Event handler for watchdog.
Arguments:
- signum (:obj:`Any`): Signal number.
- frame (:obj:`Any`): Current stack frame.
"""
raise TimeoutError()
def stop(self):
"""
Overview:
Stop watchdog with ``alarm(0)``, ``SIGALRM``, and ``SIG_DFL`` signals.
"""
signal.alarm(0)
signal.signal(signal.SIGALRM, signal.SIG_DFL)
|