Скорость копирования массива NumPy - PullRequest
0 голосов
/ 12 июня 2018

Мне интересно, есть ли недостаток в использовании b = np.array(a) вместо b = np.copy(a) для копирования массива Numpy a в b.Когда я %timeit, первый может быть на 100% быстрее.

В обоих случаях b is a равен False, и я могу манипулировать b, оставляя a нетронутым, поэтому я полагаю, что это делаетчто ожидается от .copy().

Я что-то упустил?Что плохого в использовании np.array для копирования массива?

с python 3.6.5, numpy 1.14.2, в то время как разница в скорости быстро закрывается для больших размеров:

a = np.arange(1000)

%timeit np.array(a)
501 ns ± 30.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.copy(a)  
1.1 µs ± 35.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

«Что плохого в использовании np.array для копирования массива?»

Я бы сказал, что его труднее читать.Поскольку не очевидно, что, например, array делает копию, аналогичный asarray не делает копию, если в этом нет необходимости.Читатель должен знать значение по умолчанию ключевого аргумента copy, чтобы быть уверенным.

0 голосов
/ 15 июня 2018

Как указывало AGN, np.array быстрее, чем np.copy, поскольку по сути последний является оберткой первого.Это означает, что python «теряет» дополнительное время на поиск обеих функций.Подобное происходит с декораторами.

Это дополнительное время несущественно для практических целей, и вы получаете лучшую читаемость кода.

Вы можете проверить это с помощью большого массива (где создание массива занимаетосновное время), и вы увидите очень небольшую разницу в% времени для обоих.

0 голосов
/ 12 июня 2018

Из документации numpy.copy:

Это эквивалентно:

>>> np.array(a, copy=True)

Кроме того, если вы посмотрите на исходный код :

def copy(a, order='K'):
    return array(a, order=order, copy=True)

Некоторые временные параметры:

In [1]: import numpy as np

In [2]: a = np.ascontiguousarray(np.random.randint(0, 20000, 1000))

In [3]: %timeit b = np.array(a)
562 ns ± 10.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit b = np.array(a, order='K', copy=True)
1.1 µs ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [5]: %timeit b = np.copy(a)
1.21 µs ± 9.28 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [6]: a = np.ascontiguousarray(np.random.randint(0, 20000, 1000000))

In [7]: %timeit b = np.array(a)
310 µs ± 6.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [8]: %timeit b = np.array(a, order='K', copy=True)
311 µs ± 2.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [9]: %timeit b = np.copy(a)
313 µs ± 4.33 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [10]: print(np.__version__)
1.13.3

Неожиданно, что простая явная установка параметров в их значения по умолчанию изменяет скорость выполненияnp.array().С другой стороны, возможно, просто обработка этих явных аргументов добавляет достаточно времени выполнения, чтобы иметь значение для небольших массивов.Действительно, из исходного кода для numpy.array() видно, что при предоставлении аргументов ключевого слова выполняется намного больше проверок и выполняется больше обработки, например, см. goto full_path.Если параметры ключевого слова не установлены, выполнение полностью пропускается до goto finish.Эти издержки (дополнительной обработки аргументов ключевых слов) - это то, что вы обнаруживаете в таймингах для небольших массивов.Для больших массивов эти издержки незначительны по сравнению с фактическим временем копирования массивов.

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