#python #numpy #benchmarking
#python #numpy #сравнительный анализ
Вопрос:
numpy-
arr = np.array([[1, 2, 3, 4]])
row = np.array([1, 2, 3, 4])
%timeit arr[0] = row
466 ns ± 12.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
список python —
arr = [[1, 2, 3, 4]]
row = [1, 2, 3, 4]
%timeit arr[0] = row
59.3 ns ± 2.94 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each
Разве numpy не должен быть здесь более быстрой версией?
Вот что я собираюсь сделать —
arr = np.empty((150, 4))
while True:
row = get_row_from_api()
arr[-1] = row
Комментарии:
1. Ну, здесь список переназначает один элемент, тогда как в вашем
numpy.array
примере он назначает 4 элемента. Чтобы получить справедливое сравнение, вам понадобится что-то вродеfor i, x in enumerate(row): arr[0][i] = x
2. @DevAggarwal нет, зачем тебе это нужно ? Вы могли бы использовать
numpy.ndarray
объект сdtype=object
, но тогда вы, по сути, работаете с плохим списком. Так что в этот момент просто используйте alist
вместо anumpy.ndarray
3. Потому что я хочу, чтобы моя программа работала быстрее? И я определил это как критическую часть моего кода?
4. Можете ли вы привести более конкретный пример с более реалистичным контекстом? Опять же, между a
list
и a есть довольно существенные различияnumpy.ndarray
. И не сразу понятно, что именно вы делаете со своим массивом numpy.5.
arr[-1] = row
повторно присваивает значение одной и той же последней строкеarr
. Он не выполняет пошаговое прохождение строк,
Ответ №1:
Да, использование списков python таким образом определенно было бы быстрее, потому что, когда вы назначаете что-то элементу списка python, оно не копируется, просто некоторые ссылки переназначаются (https://developers.google.com/edu/python/lists ). Вместо этого Numpy копирует все элементы из исходного контейнера в целевой. Я не уверен, нужны ли вам здесь массивы numpy, потому что их создание не является бесплатным, а списки python не такие медленные при создании (и, как мы видим, при назначении).
Комментарии:
1. Ах, в цепочке есть немного кода, который использует numpy, не уверен, стоит ли каждый раз выполнять преобразование из list -> numpy
2. Я думаю, что лучше проверить всю последовательность операций на общую производительность. Трудно сказать априори, что будет работать быстрее (если вы не умножаете матрицы [1000, 1000] или делаете что-то подобное).
3. @DevAggarwal Может быть, пора обрезать всю цепочку, а не только numpy против списка, и посмотреть, что работает лучше всего. Numpy должен быть быстрее при вычислениях . Насколько сложны ваши цепочки?
Ответ №2:
Базовая семантика этих двух операций сильно отличается. Списки Python — это массивы ссылок. Массивы Numpy — это массивы самих данных.
Строка row = get_row_from_api()
подразумевает, что новый список уже выделен.
Назначение списку as lst[-1] = row
просто записывает адрес lst
. Обычно это 4 или 8 байт.
Размещение в массиве как arr[i] = row
копирование данных. Это сокращение для arr[i, :] = row
. Каждый элемент of row
копируется в буфер of arr
. Если row
это был список, это влечет дополнительные накладные расходы на преобразование объектов python в собственные числовые типы.
Помните, что преждевременная оптимизация бессмысленна. Ваша экономия времени для одного метода по сравнению с другим, вероятно, будет незначительной. В то же время, если вам все равно понадобится массив позже по строке, скорее всего, быстрее выполнить предварительное выделение и получить небольшую скорость, а не вызывать np.array
конечный список. В первом случае вы выделяете буфер заданного размера и dtype. В последнем случае вы просто отложили накладные расходы на копирование данных, но также понесли накладные расходы на определение размера массива и dtype.