Estructuras de datos para código de volumen finito: matrices vs clases

11

Tengo que escribir un código de volumen finito para Magnetohidrodinámica (MHD). He escrito código numérico antes pero no a esta escala. Solo quería preguntar cuál sería una buena opción, usando una estructura de datos (enfoque orientado a objetos) con clases o simplemente usando múltiples matrices para diferentes propiedades, en términos de velocidad, escalabilidad, etc. Planeo escribir el código en Python, y use fortran para la parte numéricamente intensiva.

Un ejemplo para la clase en python sería

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

Las matrices se pueden definir simplemente como

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

etc.

disidente
fuente

Respuestas:

9

Respuesta simple: en python moderno, cada tipo de datos es una clase, por lo que formalmente no hay diferencia entre las dos soluciones que propuso. (Recuerde utilizar clases de estilo nuevo: ¡las clases clásicas son obsoletas! Consulte http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes )

Ahora la pregunta debería ser: ¿cómo organizo una estructura de datos eficiente en python? No hay duda de que la idea misma de organizar las células como un conjunto de class Cellinstancias es demasiado ineficiente. Terminará con un desorden de punteros y datos no relacionados con usted organizados como una lista enlazada complicada. Por supuesto, tiene la capacidad de insertar fácilmente nuevas celdas en su lista: pero ¿necesita esta función? Por el contrario, tendrá un almacenamiento de datos no contiguo y tendrá que acceder a cada celda mediante diferentes niveles de indirección.

Si organiza sus datos como datos, numpy.ndarrayentonces los datos son contiguos a la memoria, y el acceso a diferentes celdas simplemente se hace caminando a través de su bloque de memoria: espacio eficiente (no se desperdicia memoria para los punteros) y rápido .

Como señaló Ethan, los conceptos de OO deben usarse, pero a un nivel más alto, una vez que se ha implementado una estructura de datos eficiente de bajo nivel, generalmente a través numpy.ndarrayde los.

La programación OO significa vincular datos a los métodos que operan en los datos mismos en un nivel más alto de abstracción. (Un ejemplo: implementé un código FEM en el que la matriz de rigidez se definió como una clase con un método para la factorización colesky súper nodal dispersa. La primera implementación fue en el núcleo: cuando se necesitaba una implementación fuera del núcleo, esto se obtuvo mediante herencia y ajustes mínimos en el almacenamiento de datos subyacentes. Se reutilizó casi el 100% del código colesky súper nodal).

Un último comentario, pero crucial: un procedimiento numérico eficiente es el resultado de un mapeo inteligente de un algoritmo y una estructura de datos a su arquitectura de computación objetivo. Si comienza con una estructura de datos incorrecta, no hay forma de recuperar la eficiencia, sin una reescritura completa.

Stefano M
fuente
@ EthanCoon Gracias por tu comentario a la otra respuesta, que me llevó a escribir la mía.
Stefano M
10

Estaba reflexionando sobre esto hace unos días (también en Python). Personalmente, no creo que la programación orientada a objetos sea siempre una buena opción para la programación numérica. Puede distraerse con el diseño de las clases en lugar de simplemente resolver las ecuaciones. Prefiero quedarme con funciones simples, y con numpy puedes tener tus ecuaciones vectorizadas para que la cantidad de líneas que necesites sea muy pequeña. Numpy es bastante rápido porque los cálculos reales se realizan con un back-end C (¿o FORTRAN?).

Lo que te recomendaría que hagas,

  1. Escriba un script de Python que resuelva la versión más simple posible de su problema utilizando un enfoque funcional con numpy. Por ejemplo, tenga todo en una unidad arbitraria y pruebe solo 1D (o 2D). Está perfectamente bien en esta etapa si el código es desordenado. Lo importante es que está avanzando con su proyecto.
  2. Una vez que tienes algo que funciona. Identifique dónde el código es detallado y refractor. En esta etapa, puede jugar con diferentes ideas sobre cómo simplificar su código. Tal vez introduzca funciones donde note que se repite. Puede comparar con la versión original para saber que no está introduciendo errores.
  3. Decida si el enfoque orientado a objetos reducirá aún más la complejidad del código.

El mensaje principal es no comenzar a escribir clases hasta que ya haya resuelto el problema de la manera más simple posible. Solo al adquirir la experiencia de resolver un problema sabrás cómo definir tu interfaz orientada a objetos. Si hace esto de antemano, es probable que se interponga.

boyfarrell
fuente
3
Estoy en total desacuerdo con la afirmación de que OO no es una buena opción para la programación numérica, pero donde sí lo es es a un nivel mucho más alto. OO es muy útil para cosas como modelos físicos, mallas, solucionadores, etc., pero casi siempre es inapropiado a nivel de células.
Ethan Coon
En la publicación, quería advertir sobre las posibles caídas de la "objetivación prematura" del código numérico, particularmente cuando uno está comenzando. No soy adverso al uso de objetos, vea mi tercer punto: si los objetos pueden reducir la complejidad, entonces son una buena idea. Estoy de acuerdo en que los ejemplos que cita son buenos usos, pero llegar a ese punto requiere experiencia.
boyfarrell