Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: New features for timing functions (Issue #322) #340

Merged
merged 2 commits into from
Sep 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion quantecon/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .array import searchsorted
from .notebooks import fetch_nb_dependencies
from .random import check_random_state
from .timing import tic, tac, toc
from .timing import tic, tac, toc, loop_timer
86 changes: 70 additions & 16 deletions quantecon/util/tests/test_timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,86 @@
Authors: Pablo Winant
Tests for timing.py
"""

import time
from numpy.testing import assert_allclose
from nose.tools import eq_
from quantecon.util import tic, tac, toc, loop_timer


class TestTicTacToc():
def setUp(self):
self.h = 0.1
self.digits = 10

def test_timer(self):
tic()

time.sleep(self.h)
tm1 = float(tac())

time.sleep(self.h)
tm2 = float(tac())

def test_tic_tac_toc():
time.sleep(self.h)
tm3 = float(toc())

from ..timing import tic, tac, toc
import time
rtol = 0.1
for actual, desired in zip([tm1, tm2, tm3], [self.h, self.h, self.h*3]):
assert_allclose(actual, desired, rtol=rtol)

h = 0.1
def test_digits(self):
tic()

time.sleep(self.h)
tm1 = tac(self.digits)

tic()
time.sleep(self.h)
tm2 = tac(self.digits)

time.sleep(h)
el1 = tac()
time.sleep(self.h)
tm3 = toc(self.digits)

eq_(len(str(tm1).split(".")[1]), 10)
eq_(len(str(tm2).split(".")[1]), 10)
eq_(len(str(tm3).split(".")[1]), 10)

def test_output(self):
tic()

time.sleep(self.h)
tm1 = tac(self.digits, True, False)

time.sleep(h)
el2 = tac()
time.sleep(self.h)
tm2 = tac(self.digits, True, False)

time.sleep(h)
el3 = toc()
time.sleep(self.h)
tm3 = toc(self.digits, True, False)

eq_(tm1, None)
eq_(tm2, None)
eq_(tm3, None)

def test_loop(self):
def test_function_one_arg(n):
return time.sleep(n)

rtol = 0.1
for actual, desired in zip([el1, el2, el3], [h, h, h*3]):
assert_allclose(actual, desired, rtol=rtol)
def test_function_two_arg(n, a):
return time.sleep(n)

test_one_arg = loop_timer(5, test_function_one_arg, self.h, 10)
test_two_arg = loop_timer(5, test_function_two_arg, [self.h, 1], 10)
for tm in test_one_arg:
assert(abs(float(tm)-self.h)<0.01)
for tm in test_two_arg:
assert(abs(float(tm)-self.h)<0.01)

if __name__ == "__main__":

if __name__ == '__main__':
import sys
import nose

test_tic_tac_toc()
argv = sys.argv[:]
argv.append('--verbose')
argv.append('--nocapture')
nose.main(argv=argv, defaultTest=__file__)
207 changes: 188 additions & 19 deletions quantecon/util/timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class __Timer__:
'''Computes elapsed time, between tic, tac, and toc.
"""Computes elapsed time, between tic, tac, and toc.

Methods
-------
Expand All @@ -18,7 +18,10 @@ class __Timer__:
tac :
Returns and prints time elapsed since last
tic(), tac() or toc() whichever occured last.
'''
loop_timer :
Returns and prints the total and average time elapsed for n runs
of a given function.
"""

start = None
last = None
Expand All @@ -32,10 +35,29 @@ def tic(self):
self.start = t
self.last = t

def tac(self):
"""Returns and prints time elapsed since last
tic(), tac() or toc() whichever occured last."""

def tac(self, digits=2, print_output=True, output=True):
"""
Returns and prints time elapsed since last tic(), tac() or toc()
whichever occured last.

Parameters
----------
digits : scalar(int), optional(default=2)
Number of digits for time elapsed.

print_output : bool, optional(default=True)
If True, then prints time.

output : bool, optional(default=True)
If True, then returns time.

Returns
-------
tac : str
Time elapsed since last tic(), tac() or toc().

"""

import time

if self.start is None:
Expand All @@ -44,12 +66,45 @@ def tac(self):
t = time.time()
elapsed = t-self.last
self.last = t

print("TAC: Elapsed: {} seconds.".format(elapsed))
return elapsed

def toc(self):
"""Returns and prints time elapsed since last tic()."""

if print_output:
m, s = divmod(elapsed, 60)
h, m = divmod(m, 60)
print("TAC: Elapsed: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(elapsed, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

tac = rounded_time.split('.')[0] + "." + time_digits

return tac

def toc(self, digits=2, print_output=True, output=True):
"""
Returns and prints time elapsed since last tic().

Parameters
----------
digits : scalar(int), optional(default=2)
Number of digits for time elapsed.

print_output : bool, optional(default=True)
If True, then prints time.

output : bool, optional(default=True)
If True, then returns time.

Returns
-------
toc : str
Time elapsed since last tic().

"""

import time

Expand All @@ -60,9 +115,116 @@ def toc(self):
self.last = t
elapsed = t-self.start

print("TOC: Elapsed: {} seconds.".format(elapsed))
return elapsed

if print_output:
m, s = divmod(elapsed, 60)
h, m = divmod(m, 60)
print("TOC: Elapsed: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(elapsed, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

toc = rounded_time.split('.')[0] + "." + time_digits

return toc


def loop_timer(self, n, function, args=None, digits=2, print_output=True,
output=True, best_of=3):
"""
Returns and prints the total and average time elapsed for n runs
of function.

Parameters
----------
n : scalar(int)
Number of runs.

function : function
Function to be timed.

args : list, optional(default=None)
Arguments of the function.

digits : scalar(int), optional(default=2)
Number of digits for time elapsed.

print_output : bool, optional(default=True)
If True, then prints average time.

output : bool, optional(default=True)
If True, then returns average time.

best_of : scalar(int), optional(default=3)
Average time over best_of runs.

Returns
-------
average_time : str
Average time elapsed for n runs of function.

average_of_best : str
Average of best_of times for n runs of function.

"""
tic()
all_times = []
for run in range(n):
if hasattr(args, '__iter__'):
function(*args)
elif args == None:
function()
else:
function(args)
all_times.append(float(tac(digits, False, True)))

elapsed = toc(digits, False, True)

m, s = divmod(float(elapsed), 60)
h, m = divmod(m, 60)

print("Total run time: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

average_time = sum(all_times) / len(all_times)

best_times = all_times[:best_of]
average_of_best = sum(best_times) / len(best_times)

if print_output:
m, s = divmod(average_time, 60)
h, m = divmod(m, 60)
print("Average time for %d runs: %d:%02d:%0d.%0*d" %
(n, h, m, s, digits, (s%1)*(10**digits)))
m, s = divmod(average_of_best, 60)
h, m = divmod(m, 60)
print("Average of %d best times: %d:%02d:%0d.%0*d" %
(best_of, h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(average_time, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

average_time = rounded_time.split('.')[0] + "." + time_digits

rounded_time = str(round(average_of_best, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

average_of_best = rounded_time.split('.')[0] + "." + time_digits

return average_time, average_of_best


__timer__ = __Timer__()


Expand All @@ -71,11 +233,18 @@ def tic():
return __timer__.tic()


def tac():
def tac(digits=2, print_output=True, output=True):
"""Prints and returns elapsed time since last tic, tac or toc."""
return __timer__.tac()
return __timer__.tac(digits, print_output, output)


def toc():
def toc(digits=2, print_output=True, output=True):
"""Returns and prints time elapsed since last tic()."""
return __timer__.toc()
return __timer__.toc(digits, print_output, output)


def loop_timer(n, function, args=None, digits=2, print_output=True,
output=True, best_of=3):
"""Prints the total and average time elapsed for n runs of function."""
return __timer__.loop_timer(n, function, args, digits, print_output, output,
best_of)