Тестирование производительности с использованием %% timeit, скорости l oop или общего времени прошло более важно? - PullRequest
4 голосов
/ 28 февраля 2020

Я перебираю CSV-файлы со строками 10–100 тыс. Раз, поэтому производительность имеет решающее значение. Я собираюсь построчно оптимизировать каждую строку, чтобы сжать каждую долю секунды. Это просто, просто клонирование одного ряда данных. В настоящее время путают эти первоначальные результаты.

    @numba.jit()
    def test(x):
        return x

    #%%timeit
    df['source'] = df['Close']
    #79.5 µs ± 3.58 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

    #%%timeit
    df['source2'] = test(df['Close'].to_numpy())
    #88.1 µs ± 683 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Общее истекшее время быстрее в первом, но per l oop быстрее во втором. Если per l oop быстрее, я бы ожидал, что он будет быстрее в целом.

Означает ли это, что во внутреннем интерфейсе используется гораздо больше времени? Может ли кто-нибудь объяснить мне это.

Должен ли я уделять больше внимания общему прошедшему времени или времени за l oop?

Обратите внимание, я использую ноутбук Jupyter на Anaconda.

1 Ответ

0 голосов
/ 28 февраля 2020

Я могу думать только об одной вещи, которая отличается для общего времени и времени итерации. Это сборка мусора. Сборщик мусора Python время от времени проверяет, какие переменные больше не используются, и освобождает память для них. Если вы запустите один l oop, вы, вероятно, никогда не увидите его работоспособным. Но если он работает дольше, чем, скорее всего, он срабатывает и начинает освобождать память, что занимает много времени. Поэтому, если во время l oop было выделено гораздо больше памяти, сборщику мусора требуется больше времени для освобождения памяти.

Это размышление приводит к одному возможному улучшению вашего кода: Помните, сколько вы выделяете памяти.

df['source'] = df['Close'] может означать, что вы копируете свои данные из одного столбца в другой. Старайтесь максимально использовать данные. Например, выполните col1 = df['Close'], а затем используйте col1 для дальнейших манипуляций. Таким образом, данные не копируются и это быстрее (в случае, если вам не нужен столбец source и он используется временно).

Существует также другая возможность ускорить процесс, не выделяя и не выделяя память , При использовании Numba быстрее выполнять итерации по всем строкам и выполнять вычисления за один go вместо многократного повторения по одним и тем же данным при использовании векторных формул Numpy / Pandas. Вы не только экономите на повторении данных несколько раз, но даже можете использовать переменные стека вместо кучи (терминология, относящаяся только к скомпилированному коду. Python сохраняет все в куче). Используя переменные стека в Numba, вы по существу прекращаете выделять и освобождать память постоянно.

Другой вариант может заключаться в том, чтобы предварительно выделять переменные перед большим l oop и повторно использовать их для каждой итерации l oop. Но это помогает, только если у вас есть стабильный размер переменной для каждой итерации (в вашем случае это число строк для каждого CSV-файла)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...