¿Qué es el diseño orientado a datos?


156

Estaba leyendo este artículo , y este tipo continúa hablando de cómo todos pueden beneficiarse enormemente al mezclar el diseño orientado a datos con OOP. Sin embargo, no muestra ningún ejemplo de código.

Busqué en Google esto y no pude encontrar ninguna información real sobre qué es esto, y mucho menos cualquier muestra de código. ¿Alguien está familiarizado con este término y puede proporcionar un ejemplo? ¿Es esta quizás una palabra diferente para otra cosa?


77
Ese artículo en Game developer ahora está disponible en un blog fácil de leer: gamesfromwithin.com/data-oriented-design
Edmundito

58
¿Alguna vez buscaron en Google algo, encontraron una buena pregunta SO específica y luego se dieron cuenta de que fueron ustedes quienes la formularon hace años?
ryeguy

1
Aquí hay un agregado de contenido DOD en la web
legends2k

14
@ryeguy, tuve una pregunta, busqué en Google, encontré una buena pregunta SO, y luego me di cuenta de que la respondí hace años.
Michael Deardeuff

44
Busqué en Google algo y encontré una buena pregunta SO y adivina qué. No fui yo quien preguntó ni quién respondió :)
Nadjib Mami

Respuestas:


288

En primer lugar, no confunda esto con el diseño basado en datos.

Comprendo que el diseño orientado a datos consiste en organizar sus datos para un procesamiento eficiente. Especialmente con respecto a las fallas de caché, etc. El diseño impulsado por datos, por otro lado, se trata de permitir que los datos controlen gran parte del comportamiento de sus programas (descrito muy bien por la respuesta de Andrew Keith ).

Supongamos que tiene objetos de bola en su aplicación con propiedades como color, radio, rebote, posición, etc.

Enfoque orientado a objetos

En OOP describirías bolas como esta:

class Ball {
  Point  position;
  Color  color;
  double radius;

  void draw();
};

Y luego crearías una colección de bolas como esta:

vector<Ball> balls;

Enfoque orientado a datos

Sin embargo, en el diseño orientado a datos, es más probable que escriba el código de esta manera:

class Balls {
  vector<Point>  position;
  vector<Color>  color;
  vector<double> radius;

  void draw();
};

Como puede ver, ya no hay una sola unidad que represente una Bola. Los objetos de bola solo existen implícitamente.

Esto puede tener muchas ventajas, en cuanto al rendimiento. Por lo general, queremos realizar operaciones en muchas bolas al mismo tiempo. El hardware generalmente quiere grandes porciones continuas de memoria para operar de manera eficiente.

En segundo lugar, puede realizar operaciones que afecten solo una parte de las propiedades de las bolas. Por ejemplo, si combina los colores de todas las bolas de varias maneras, entonces desea que su caché solo contenga información de color. Sin embargo, cuando todas las propiedades de la bola se almacenan en una unidad, también atraerá todas las demás propiedades de una bola. Aunque no los necesites.

Ejemplo de uso de caché

Digamos que cada bola ocupa 64 bytes y un punto toma 4 bytes. Una ranura de caché toma, digamos, 64 bytes también. Si quiero actualizar la posición de 10 bolas, tengo que extraer 10 * 64 = 640 bytes de memoria en el caché y obtener 10 errores de caché. Sin embargo, si puedo trabajar las posiciones de las bolas como unidades separadas, eso solo tomará 4 * 10 = 40 bytes. Eso cabe en una búsqueda de caché. Por lo tanto, solo obtenemos 1 falta de caché para actualizar las 10 bolas. Estos números son arbitrarios: supongo que un bloque de caché es más grande.

Pero ilustra cómo el diseño de la memoria puede tener un efecto severo en los éxitos de caché y, por lo tanto, en el rendimiento. Esto solo aumentará en importancia a medida que se amplíe la diferencia entre la velocidad de CPU y RAM.

Cómo diseñar la memoria

En mi ejemplo de bola simplifiqué mucho el problema, porque generalmente para cualquier aplicación normal es probable que accedan a múltiples variables juntas. Por ejemplo, la posición y el radio probablemente se usarán juntos con frecuencia. Entonces su estructura debería ser:

class Body {
  Point  position;
  double radius;
};

class Balls {
  vector<Body>  bodies;
  vector<Color>  color;

  void draw();
};

La razón por la que debe hacer esto es que si los datos utilizados juntos se colocan en matrices separadas, existe el riesgo de que compitan por los mismos espacios en la memoria caché. Así, cargar uno arrojará al otro.

Entonces, en comparación con la programación orientada a objetos, las clases que terminas haciendo no están relacionadas con las entidades en tu modelo mental del problema. Dado que los datos se agrupan en función del uso de datos, no siempre tendrá nombres razonables para dar a sus clases en Diseño orientado a datos.

Relación con bases de datos relacionales

El pensamiento detrás del diseño orientado a datos es muy similar a cómo piensa sobre las bases de datos relacionales. La optimización de una base de datos relacional también puede implicar el uso de la memoria caché de manera más eficiente, aunque en este caso, la memoria caché no es la memoria caché de la CPU sino páginas en la memoria. Un buen diseñador de bases de datos también probablemente dividirá los datos a los que se accede con poca frecuencia en una tabla separada en lugar de crear una tabla con una gran cantidad de columnas, donde solo se utilizan algunas de las columnas. También podría elegir desnormalizar algunas de las tablas para que no se tenga que acceder a los datos desde múltiples ubicaciones en el disco. Al igual que con el diseño orientado a datos, estas elecciones se realizan al observar cuáles son los patrones de acceso a datos y dónde está el cuello de botella en el rendimiento.


44
Gracias por esto, lo explicaste muy bien.
ryeguy

44
bien dicho; Sin embargo, solo tengo una pregunta. Digamos que tenemos una estructura struct balls {vector<vec3> pos; vector<vec3> velocity;}, no actualizar la posición de cada bola en realidad golpea el caché ya que se movería hacia adelante y hacia atrás entre el vector de velocidad y el vector de posición (sí, máquinas modernas y líneas de caché y todo eso, esto es también solo una ilustración)?
falstro

14
Que podría. Pero recuerde que no se extraerá toda la matriz pos a la vez. Solo una línea de caché, y posiblemente alguna captación previa. Del mismo modo con la velocidad. Entonces, para que se tiren entre sí, cada trozo correspondiente de pos y vector tiene que asignarse a la misma línea de caché. Eso puede suceder, por eso, la recomendación es poner las variables que se usan juntas en una estructura. Entonces, por ejemplo, la velocidad y la posición estarían en un vector mientras que el color estaría en otro vector.
Erik Engheim

1
@roe Debe agrupar las propiedades a las que se accede juntas. Entre propiedades no debe haber dependencias en absoluto. Entonces esta estructura sería mejor struct balls { vector<color> colors; vector<body> bodies; /* contains position and velocity */ }.
danijar

2
@danijar Actualicé la explicación con tus sugerencias. Podría haber dicho mucho más sobre esto, pero eso realmente se convertirá en un artículo.
Erik Engheim

18

Mike Acton dio una charla pública sobre diseño orientado a datos recientemente:

Mi resumen básico sería: si desea rendimiento, piense en el flujo de datos, encuentre la capa de almacenamiento que es más probable que se atornille y optimice para ello . Mike se está centrando en las fallas de caché L2, porque lo está haciendo en tiempo real, pero imagino que lo mismo se aplica a las bases de datos (lecturas de disco) e incluso a la Web (solicitudes HTTP). Es una forma útil de hacer programación de sistemas, creo.

Tenga en cuenta que no lo exime de pensar en algoritmos y complejidad de tiempo, solo enfoca su atención en descubrir el tipo de operación más costoso al que luego debe enfocarse con sus habilidades locas de CS.


14

Solo quiero señalar que Noel está hablando específicamente sobre algunas de las necesidades específicas que enfrentamos en el desarrollo de juegos. Supongo que otros sectores que están haciendo simulación suave en tiempo real se beneficiarían de esto, pero es poco probable que sea una técnica que muestre una mejora notable en las aplicaciones comerciales generales. Esta configuración es para garantizar que se exprima hasta el último bit del rendimiento del hardware subyacente.


Convenido. Algunas otras áreas donde el diseño orientado a datos es significativo son: hardware y firmware para dispositivos de gran ancho de banda (por ejemplo, redes o almacenamiento); computación científica a gran escala (por ejemplo, simulación del clima, plegamiento de proteínas), procesamiento de señales (por ejemplo, audio, imagen, video), compresión de datos. Estos se enmarcan en la "Ciencia e Ingeniería Computacional", que a veces se ofrece como una especialización separada de la Ciencia de la Computación más típica.
rwong

-3

Un diseño orientado a datos es un diseño en el que la lógica de la aplicación se basa en conjuntos de datos, en lugar de algoritmos de procedimiento. Por ejemplo

Enfoque procesal.

int animation; // this value is the animation index

if(animation == 0)
   PerformMoveForward();
else if(animation == 1)
  PerformMoveBack();
.... // etc

enfoque de diseño de datos

typedef struct
{
   int Index;
   void (*Perform)();
}AnimationIndice;

// build my animation dictionary
AnimationIndice AnimationIndices[] = 
  {
      { 0,PerformMoveForward }
      { 1,PerformMoveBack }
  }

// when its time to run, i use my dictionary to find my logic
int animation; // this value is the animation index
AnimationIndices[animation].Perform();

Los diseños de datos como este promueven el uso de datos para construir la lógica de la aplicación. Es más fácil de administrar, especialmente en los videojuegos que pueden tener miles de rutas lógicas basadas en animación u otro factor.


14
Esto en realidad no es correcto. Está confundiendo el diseño orientado a datos con el diseño impulsado por datos. Hice lo mismo hasta que leí el artículo de Noel y me di cuenta de que estaba hablando de algo completamente diferente.
Erik Engheim

12
Además, Indice no es una palabra. Hay "índice" e "índices" y algunos incluso toleran los "índices", pero "índice" nunca es correcto.
Baxissimo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.