Python numpy и эффективность памяти (перейдите по ссылке и стоимости)

Я недавно использовал python вместо c/С++, потому что он сокращает время кодирования в несколько раз. В то же время, когда я обрабатываю большие объемы данных, скорость, с которой запускаются мои программы на python, начинает становиться намного медленнее, чем в c. Мне интересно, не связано ли это с использованием больших объектов/массивов неэффективно. Есть ли всестороннее руководство только для того, как память обрабатывается numpy/python? Когда вещи передаются по ссылке и когда по значению, когда вещи копируются, а когда нет, какие типы изменяемы, а какие нет.

Ответ 1

Объекты в python (и большинстве основных языков) передаются в качестве ссылки.

Если мы возьмем numpy, например, "новые" массивы, созданные путем индексирования существующих, представляют собой только виды оригинала. Например:

import numpy as np

>>> vec_1 = np.array([range(10)])
>>> vec_1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> vec_2 = vec_1[3:] # let vec_2 be vec_1 from the third element untill the end
>>> vec_2
array([3, 4, 5, 6, 7, 8, 9])
>>> vec_2[3] = 10000
array([3, 4, 5, 10000, 7, 8, 9])
>>> vec_1
array([0, 1, 2, 3, 4, 5, 10000, 7, 8, 9])

У Numpy есть удобный способ помочь с вашими вопросами, называемый may_share_memory (obj1, obj2). Итак:

>>> np.may_share_memory(vec_1, vec_2)
True

Просто будьте осторожны, потому что метод возвращает ложные срабатывания (хотя я никогда не видел его).

На SciPy 2013 был учебник по numpy (http://conference.scipy.org/scipy2013/tutorial_detail.php?id=100). В конце парень говорит немного о том, как numpy обрабатывает память. Смотрите его.

Как правило, объекты почти никогда не передаются как значение по умолчанию. Даже те, которые инкапсулированы на другой объект. Другой пример, когда список совершает экскурсию:

Class SomeClass():

    def __init__(a_list):
        self.inside_list = a_list

    def get_list(self):
        return self.inside_list

>>> original_list = range(5)
>>> original_list
[0,1,2,3,4]
>>> my_object = SomeClass(original_list)
>>> output_list = my_object.get_list()
>>> output_list
[0,1,2,3,4]
>>> output_list[4] = 10000
>>> output_list
[0,1,2,3,10000]
>>> my_object.original_list
[0,1,2,3,10000]
>>> original_list
[0,1,2,3,10000]

Жутко, да? Используя символ назначения ( "=" ) или возвращающий один в конце функции, вы всегда будете создавать указатель на объект или его часть. Объекты дублируются, когда вы явно делаете это, используя метод копирования, например some_dict.copy, или массив [:]. Например:

>>> original_list = range(5)
>>> original_list
[0,1,2,3,4]
>>> my_object = SomeClass(original_list[:])
>>> output_list = my_object.get_list()
>>> output_list
[0,1,2,3,4]
>>> output_list[4] = 10000
>>> output_list
[0,1,2,3,10000]
>>> my_object.original_list
[0,1,2,3,10000]
>>> original_list
[0,1,2,3,4]

Получил?

Ответ 2

Итак, мне нужно будет указать EOL на это, потому что я думаю, что его ответ очень важен:

3) Последняя точка связана с заголовком вопроса: "передача по значению" и "передача по ссылке" не являются понятиями, которые актуальны в Python. Соответствующие понятия вместо этого являются "изменчивым объектом" и "неизменный объект". Списки являются изменяемыми, а числа - нет, что объясняет, что вы наблюдаете. Кроме того, ваши объекты Person1 и bar1 mutable (почему вы можете изменить возраст человека). Ты можешь найти больше информации об этих понятиях в текстовом учебнике и видео руководство. В Википедии есть и другая (более техническая) информация. пример иллюстрирует разницу в поведении между изменчивыми и неизменный - ответ EOL

В общем, я нашел Numpy/Scipy, следуя этим; что более важно, они прямо говорят вам в документах, что происходит.

Например np.random.shuffle запрашивает входной массив и возвращает None, а np.random.permutation возвращает массив. Вы можете четко видеть, какой из них возвращает значение, а не здесь.

Симметричные массивы имеют семантику pass-by-reference, и в целом я нахожу Numpy/Scipy очень эффективным.

Я думаю, справедливо сказать, что если быстрее использовать pass-by-reference, они будут. Пока вы используете функции так, как говорят документы, у вас не должно быть серьезных проблем в отношении скорости.


есть ли какой-либо тип, о котором вы спрашиваете?