Сравнение скорости.NumPy против стандарта Python - PullRequest
0 голосов
/ 02 октября 2018

Я провел несколько экспериментов и обнаружил несколько случаев, когда стандартные библиотеки Python random и math работают быстрее, чем аналог numpy.

Я думаю, что есть тенденция к тому, что стандартная библиотека Python примерно в 10 раз быстрее для мелкомасштабных операций, тогда как numpy намного быстрее для крупномасштабных (векторных) операций.Я предполагаю, что numpy имеет некоторые накладные расходы, которые становятся доминирующими для небольших дел.

Мой вопрос: верна ли моя интуиция?И будет ли вообще целесообразно использовать стандартную библиотеку вместо numpy для небольших (обычно скалярных) операций?

Примеры приведены ниже.

import math
import random
import numpy as np

Журнал и экспоненциальный

%timeit math.log(10)
# 158 ns ± 6.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit np.log(10)
# 1.64 µs ± 93.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit math.exp(3)
# 146 ns ± 8.57 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit np.exp(3)
# 1.72 µs ± 78.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Генерация нормального распределения

%timeit random.gauss(0, 1)
# 809 ns ± 12.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.normal()
# 2.57 µs ± 14.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Выбор случайного элемента

%timeit random.choices([1,2,3], k=1)
# 1.56 µs ± 55.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.choice([1,2,3], size=1)
# 23.1 µs ± 1.04 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

То же самое с массивом NumPy

arr = np.array([1,2,3])

%timeit random.choices(arr, k=1)
# 1.72 µs ± 33.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.choice(arr, size=1)
# 18.4 µs ± 502 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

С большим массивом

arr = np.arange(10000)

%timeit random.choices(arr, k=1000)
# 401 µs ± 6.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.random.choice(arr, size=1000)
# 41.7 µs ± 1.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

NumPy используется в основном для производительности с массивами .Это зависит от использования смежных блоков памяти и более эффективной итерации более низкого уровня.Применение математической функции NumPy к скаляру или вычисление случайного числа не являются векторизованными операциями.Это объясняет поведение, которое вы видите.

См. Также Каковы преимущества NumPy по сравнению с обычными списками Python?

И будет ли это вообще целесообразноиспользовать стандартную библиотеку вместо NumPy для небольших (обычно скалярных) операций?

Редко, когда узкое место для программы вызвано операциями со скалярами.На практике различия незначительны.Так что в любом случае это хорошо.Если вы уже используете NumPy, нет никакого вреда в том, чтобы продолжать использовать операции NumPy со скалярами.

Стоит сделать особый случай вычисления случайных чисел.Как и следовало ожидать, случайное число, выбранное с помощью random против NumPy, может не совпадать:

assert random.gauss(0, 1) == np.random.normal()  # AssertionError
assert random.choices(arr, k=1)[0] == np.random.choice(arr, size=1)[0]  # AssertionError

У вас есть дополнительные функции в NumPy, чтобы сделать случайные числа «предсказуемыми».Например, повторный запуск приведенного ниже сценария будет всегда приводить к одному и тому же результату:

np.random.seed(0)
np.random.normal()

То же относится и к np.random.choice.Таким образом, существуют различия в способе получения случайного числа и доступной функциональности.Для тестирования или других целей вы можете захотеть получить согласованные «случайные» числа.

0 голосов
/ 02 октября 2018

numpy - это только улучшение производительности для больших блоков данных.Затраты на проверку правильности выравнивания блоков памяти перед заливкой ndarray в скомпилированную с * функцию numpy в общем случае могут привести к потере времени, если массив не сравнительно большой.Вот почему так много numpy вопросов в основном «Как мне взять этот зацикленный код и сделать его быстрым», и почему в этом теге он считается действительным, когда почти любой другой тег приведет вас к Проверка кода прежде чем они пройдут титул.

Итак, да, ваши наблюдения обобщаемы.Векторизация - это весь смысл numpy.numpy код, который не векторизован, всегда медленнее, чем голый код python, и, возможно, так же «неправильн», как взлом одного грецкого ореха отбойным молотком.Либо найдите подходящий инструмент, либо получите больше орехов.

...