Лучше использовать кортеж или массив numpy для хранения координат

Я портирую научное приложение C++ на python, и поскольку я новичок в python, некоторые проблемы приходят мне на ум:

1) я определяю класс, который будет содержать координаты (x,y). Эти значения будут доступны несколько раз, но они будут считываться только после создания экземпляра класса. Лучше ли использовать кортеж или массив numpy, как в памяти, так и во времени доступа?

2) в некоторых случаях, эти координаты будут использоваться для построения комплексного числа, оценивать по сложная функция, и будет использоваться реальная часть этой функции. Предполагая, что нет способа разделить реальную и сложную части этой функции, а реальная часть должна будет использоваться в конце, может быть,лучше использовать непосредственно комплексные числа для хранения (x, y)? Насколько плохи накладные расходы при преобразовании из сложных в реальные в python? Код на c++ делает много этих преобразований, и это большое замедление в этом коде.

3) также некоторые преобразования координат необходимо будет выполнить, и для координат значения x и y будут доступны отдельно, преобразование будет выполнено, и результат будет возвращен. Преобразования координат определяются в комплексной плоскости, поэтому все еще быстрее использовать компоненты x и y напрямую, чем полагаться на комплексные переменные?

спасибо

2 ответов


С точки зрения потребления памяти массивы numpy более компактны, чем кортежи Python. Массив numpy использует один непрерывный блок памяти. Все элементы массива numpy должны иметь объявленный тип (например, 32-разрядный или 64-разрядный float.) Кортеж Python не обязательно использует непрерывный блок памяти, а элементы кортежа могут быть произвольными объектами Python, которые обычно потребляют больше памяти, чем числовые типы numpy.

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

Что касается скорости, я думаю, что выбор сводится к вопросу: "Можете ли вы векторизовать свой код?"

то есть, вы можете выразить свои вычисления как операции, выполняемые на всех массивах по элементам.

если код может быть векторизован, то numpy, скорее всего, будет быстрее, чем кортежи Python. (Единственный случай, когда я мог представить, где его может не быть, - это если бы у вас было много очень маленьких кортежи. В этом случае накладные расходы на формирование массивов numpy и единовременная стоимость импорта numpy могут заглушить преимущество векторизации.)

пример кода, который не может быть векторизован, был бы, если бы ваш расчет включал просмотр, скажем, первого комплексного числа в массиве z, выполнение вычисления, которое производит целочисленный индекс idx, после получения z[idx], делая расчет на то число, которое производит следующий индекс idx2, после получения z[idx2], etc. Этот тип вычислений не может быть векторизуемым. В этом случае вы также можете использовать кортежи Python, так как вы не сможете использовать силу numpy.

Я бы не беспокоился о скорости доступа к реальным/мнимым частям комплексного числа. Я предполагаю, что проблема векторизации, скорее всего, определит, какой метод быстрее. (Хотя, кстати, numpy может преобразовать массив комплексных чисел в их реальные части, просто пройдя по комплексу массив, пропуская каждый другой поплавок и просматривая результат как поплавки. Более того, синтаксис предельно прост: If z представляет собой сложный массив numpy, затем z.real реальные части как массив NumPy поплавка. Это должно быть намного быстрее, чем чистый подход Python к использованию понимания списка поиска атрибутов:[z.real for z in zlist].)

просто из любопытства, какова причина переноса кода C++ на Python?


A numpy массив с дополнительным измерением плотнее в использовании памяти и, по крайней мере, так же быстро! как numpy массив кортежей; комплексные числа, по крайней мере, так же хороши или даже лучше, в том числе для вашего третьего вопроса. Кстати, вы, возможно, заметили , что-в то время как вопросы, заданные позже, чем ваши, получали ответы в изобилии-ваш лежал под паром: часть причины, несомненно, в том, что спрашивая три вопросы в рамках вопроса отключает ответчиков. Почему бы просто не задать один вопрос вопрос? Знаешь, тебя ведь не обвиняют в вопросах или чем-то подобном...!-)