Skip to content
log.py 34.7 KiB
Newer Older
def time_and_count_function(f, timer, counter=None, increment=1):
    def inner_f(*args, **kwargs):
        if counter is not None:
            counter.add(increment)
        sub_timer = timer.start_sub_timer()
        try:
            return f(*args, **kwargs)
        finally:
            sub_timer.stop().submit()
class TimestepCounter(LogQuantity):
    """Counts the number of times L{LogManager.tick} is called."""

    def __init__(self, name="step"):
        LogQuantity.__init__(self, name, "1", "Timesteps")
        self.steps = 0

    def __call__(self):
        result = self.steps
        self.steps += 1
        return result




class TimestepDuration(PostLogQuantity):
    """Records the CPU time between invocations of 
    :meth:`LogManager.tick_before` and 
    :meth:`LogManager.tick_after`.
    """
    def __init__(self, name="t_step"):
        PostLogQuantity.__init__(self, name, "s", "Time step duration")
    def prepare_for_tick(self):
        self.last_start = time()

    def __call__(self):
        now = time()
        result = now - self.last_start
class CPUTime(LogQuantity):
    """Records (monotonically increasing) CPU time."""
    def __init__(self, name="t_cpu"):
        LogQuantity.__init__(self, name, "s", "Wall time")

        self.start = time()

    def __call__(self):
        return time()-self.start




Andreas Klöckner's avatar
Andreas Klöckner committed
class ETA(LogQuantity):
    """Records an estimate of how long the computation will still take."""
    def __init__(self, total_steps, name="t_eta"):
        LogQuantity.__init__(self, name, "s", "Estimated remaining duration")

        self.steps = 0
        self.total_steps = total_steps
        self.start = time()

    def __call__(self):
        fraction_done = self.steps/self.total_steps
        self.steps += 1
        time_spent = time()-self.start
        if fraction_done > 1e-9:
            return time_spent/fraction_done-time_spent
        else:
            return 0




def add_general_quantities(mgr):
    """Add generally applicable L{LogQuantity} objects to C{mgr}."""

    mgr.add_quantity(TimestepDuration())
    mgr.add_quantity(CPUTime())
    mgr.add_quantity(LogUpdateDuration(mgr))
    mgr.add_quantity(TimestepCounter())




class SimulationTime(TimeTracker, LogQuantity):
    """Record (monotonically increasing) simulation time."""

    def __init__(self, dt, name="t_sim", start=0):
        LogQuantity.__init__(self, name, "s", "Simulation Time")
        TimeTracker.__init__(self, dt)

    def __call__(self):
class Timestep(SimulationLogQuantity):
    """Record the magnitude of the simulated time step."""

    def __init__(self, dt, name="dt", unit="s"):
        SimulationLogQuantity.__init__(self, dt, name, unit, "Simulation Timestep")
    """Set the simulation timestep on L{LogManager} C{mgr} to C{dt}."""

    for gd_lst in [mgr.before_gather_descriptors,
            mgr.after_gather_descriptors]:
        for gd in gd_lst:
            if isinstance(gd.quantity, DtConsumer):
                gd.quantity.set_dt(dt)
def add_simulation_quantities(mgr, dt=None):
    """Add L{LogQuantity} objects relating to simulation time."""
    if dt is not None:
        from warnings import warn
        warn("Specifying ahead of time is a deprecated practice. "
                "Use pytools.log.set_dt() instead.")

    mgr.add_quantity(SimulationTime(dt))
    """Add generic run metadata, such as command line, host, and time."""

    mgr.set_constant("cmdline", " ".join(sys.argv))
    mgr.set_constant("machine", gethostname())
    from time import localtime, strftime, time
    mgr.set_constant("date", strftime("%a, %d %b %Y %H:%M:%S %Z", localtime()))
    mgr.set_constant("unixtime", time())