Как использовать timeit, когда каждый тест требует случайной настройки

У меня есть функция f(x), которая принимает в качестве входных данных список x из 100 случайных чисел с плавающей точкой от 0 до 1. Различные списки приведут к разным временам выполнения f.

Я хочу узнать, сколько времени в среднем требуется f для большого количества различных случайных списков. Как лучше всего это сделать? Должен ли я использовать timeit, и если да, то есть ли способ сделать это, не включая время, необходимое для создания каждого случайного списка в каждом испытании?

Вот как бы я это сделал без timeit (псевдокод):

for i = 1 to 10000:
    x = random list
    start = current time
    f(x)
    end = current time
    results.append(end - start)
return mean(results)

person Flash    schedule 26.10.2013    source источник
comment
stackoverflow.com/questions/2245161/   -  person sve    schedule 26.10.2013
comment
@lnwvr, лол, я никогда этого не видел. Если бы я это сделал, я бы просто скопировал его, не нужно было делать свой собственный декоратор! :П   -  person Games Brainiac    schedule 26.10.2013


Ответы (3)


Вы можете сделать декоратор таймера:

Вот пример кода:

from time import time


class Timer(object):
    def __init__(self, func):
        """
        Decorator that times a function
        @param func: Function being decorated
        @type func: callable
        """
        self.func = func

    def __call__(self, *args, **kwargs):
        start = time()
        self.func(*args, **kwargs)
        end = time()
        return end - start


@Timer
def cheese():
    for var in xrange(9999999):
        continue

for var in xrange(100):
    print cheese()

Рабочий пример с меньшим количеством циклов.

person Games Brainiac    schedule 26.10.2013

import timeit, random

def summer(myList):
    result = 0
    for num in myList:
        result += num
    return result

for i in range(10):
    x = [random.randint(0, 100) for i in range(100000)]
    print timeit.timeit("summer(x)", setup="from __main__ import x, summer", number = 100)

Вы можете импортировать переменную, используя from __main__ import x

person thefourtheye    schedule 26.10.2013
comment
Разве вызов timeit несколько раз в цикле не противоречит цели его использования? - person Flash; 26.10.2013
comment
@Andrew Эндрю Вы хотели каждый раз тестировать функцию со случайными входными данными, верно? Вот почему он в цикле со случайным вводом каждый раз. - person thefourtheye; 26.10.2013
comment
@Andrew Это то же самое, но с timeit способом сделать это. - person thefourtheye; 26.10.2013
comment
timeit не такой гибкий, как хотелось бы. Тем не менее, это способ, которым вы можете достичь того, чего хотите. - person Games Brainiac; 26.10.2013

Я думаю, что это делает свое дело. Он будет выполнять setup один раз за повтор, а затем выполнять stmt number=1 раз. Однако я не думаю, что это намного лучше, чем простой цикл, который вы опубликовали.

import timeit

stmt = '[x*x*x for x in xrange(n)]'  # just an example 
setup = 'import random; n = random.randint(10, 100)'
r = 10000
times = timeit.repeat(stmt, setup, repeat=r, number=1)

print min(times), max(times), sum(times)/r

Существует также «режим ячейки», который вы можете использовать с timeit в оболочке IPython, но он возвращает только время поста, и нет простого способа его изменить (?).

import random

%%timeit -r 10000 -n 1 n = random.randint(10,100)
var = [x*x*x for x in xrange(n)]
person Community    schedule 26.10.2013