Я работал над приложением, критичным к производительности, которое часто требует создания копий двумерного списка целых чисел и изменения копии (я реализую минимаксный алгоритм).
Я заметил там огромная разница в производительности между копией и глубокой копией в списках с одинаковым количеством элементов, и я хотел бы понять, правильно ли мое мышление.
Воспроизвести моипроблема, запустите следующий код:
import numpy as np
np.random.seed(0)
lst1 = np.random.randint(100, size=1000 * 1000).tolist()
lst2 = np.random.randint(100, size=(1000, 1000)).tolist()
Теперь, синхронизируя приведенные ниже утверждения, вы должны увидеть моменты, похожие на мои.
%timeit copy.copy(lst1)
%timeit lst1.copy()
%timeit copy.deepcopy(lst2)
5 ms ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
5.47 ms ± 551 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.61 s ± 112 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Оба lst1
и lst2
имеютмиллион элементов, но надежное копирование первого в 200 раз быстрее, чем вложенный список с таким же количеством элементов.Я подумал, что это связано с тем фактом, что создание глубоких копий вложенных списков может потребовать некоторой рекурсивной реализации, которая будет медленной, поэтому я попытался
%timeit copy.deepcopy(lst1)
1.43 s ± 90.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
И время все еще показывает значительное замедление.Я проверил документы , но объяснений было мало.Однако по времени я подозреваю, что deepcopy
копирует также каждый int , создавая новые целые числа.Но это похоже на расточительство.
Правильно ли я здесь думаю?Что делает здесь глубокая копия, а list.copy
и мелкая копия этого не делают?
Я видел, что deepcopy () очень медленно , но, похоже, вопрос требует альтернативы, а необъяснение (мне не было понятно).