Структуры данных для кода конечного объема: массивы против классов

11

Я должен написать код конечного объема для магнитной гидродинамики (МГД). Я написал числовой код раньше, но не в этом масштабе. Я просто хотел спросить, какой будет хорошим выбором, используя структуру данных (объектно-ориентированный подход) с классами или просто используя несколько массивов для разных свойств, с точки зрения скорости, масштабируемости и т. Д. Я планирую написать код на Python, и используйте fortran для численно интенсивной части.

Примером для класса в Python будет

class Cell:
   def __init__(self, x, y, z, U):

Массивы могут быть просто определены как

x[nx][ny][nz]
y[nx][ny][nz]
z[nx][ny][nz]
U[nx][ny][nz]

и т.п.

инакомыслящий
источник

Ответы:

9

Простой ответ: в современном Python каждый тип данных является классом, поэтому формально нет никакой разницы между двумя предложенными вами решениями. (Пожалуйста, не забудьте использовать классы нового стиля: классические классы устарели! См. Http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes )

Теперь вопрос должен быть: как организовать эффективную структуру данных в Python? Нет сомнений в том, что сама идея организации ячеек в виде множества class Cellэкземпляров слишком неэффективна. Вы получите путаницу указателей и неконкурентных данных, организованных как сложный связанный список. Конечно, у вас есть возможность легко добавлять новые ячейки в ваш список: но нужна ли вам эта функция? Напротив, у вас будет несмежное хранилище данных, и вы должны получить доступ к каждой ячейке с разными уровнями косвенности.

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

Как отметил Итан, концепции ОО следует использовать, но на более высоком уровне, после того как эффективная структура данных низкого уровня будет реализована, обычно через numpy.ndarrays.

ОО-программирование означает привязку данных к методам, которые работают с самими данными на более высоком уровне абстракции. (Пример: я реализовал код FEM, в котором матрица жесткости была определена как класс с методом разреженной суперузловой факторизации Холецкого. Первая реализация была внутренней: когда требовалась внешняя реализация, это был получен с помощью наследования и минимальных изменений в хранилище подчеркивающих данных. Почти 100% супер-узлового кода cholesky было использовано повторно.)

Последний комментарий, но важный: эффективная числовая процедура является результатом умного сопоставления алгоритма и структуры данных с вашей целевой вычислительной архитектурой. Если вы начнете с неправильной структуры данных, невозможно восстановить эффективность без полного переписывания.

Стефано М
источник
@EthanCoon Спасибо за ваш комментарий к другому ответу, который побудил меня написать свой собственный.
Стефано М
10

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

Что я бы порекомендовал вам сделать,

  1. Напишите скрипт на Python, который решает простейшую версию вашей проблемы, используя функциональный подход с numpy. Например, все в произвольной единице и попробуйте только 1D (или 2D). На этом этапе совершенно нормально, если код грязный. Важно то, что вы продвигаетесь вперед со своим проектом.
  2. Как только у вас есть что-то, что работает. Определите, где код является многословным и рефракторным. На этом этапе вы можете поиграть с различными идеями о том, как упростить ваш код. Может быть, ввести функции, когда вы замечаете, что повторяете себя Вы можете сравнить с оригинальной версией, чтобы знать, что вы не вносите ошибки.
  3. Решите, будет ли объектно-ориентированный подход еще больше уменьшать сложность кода.

Главное сообщение - не начинайте писать классы, пока вы не решите проблему самым простым способом. Только на основе опыта решения проблемы вы узнаете, как определить свой объектно-ориентированный интерфейс. Если вы сделаете это заранее, это может помешать вам.

boyfarrell
источник
3
Я категорически не согласен с утверждением, что ОО не подходит для численного программирования, но где оно подходит, находится на гораздо более высоком уровне. ОО очень полезен для таких вещей, как физические модели, сетки, решатели и т. Д., Но почти всегда неуместен на уровне ячеек.
Итан Кун
В посте я хотел предупредить о возможных провалах «преждевременной объективизации» числового кода, особенно когда он только начинается. Я не против использования объектов, см. Мой третий пункт: если объекты могут уменьшить сложность, то это хорошая идея. Я согласен с тем, что приведенные вами примеры являются хорошим использованием, но для достижения этой цели требуется опыт.
Boyfarrell