Что такое ориентированный на данные дизайн?

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

Я искал это и не мог найти никакой реальной информации о том, что это такое, не говоря уже о каких-либо образцах кода. Кто-нибудь знаком с этим термином и может служить примером? Разве это может быть другое слово для чего-то еще?

Ответ 1

Прежде всего, не путайте это с конструкцией, управляемой данными.

Мое понимание Data Oriented Design заключается в организации ваших данных для эффективной обработки. Особенно в отношении промахов кэш-памяти и т.д. Data Driven Design, с другой стороны, позволяет управлять данными по многим вашим программам (очень хорошо описано Andrew Keith answer).

Скажите, что у вас есть объекты шара в вашем приложении со свойствами, такими как цвет, радиус, bounciness, положение и т.д.

Объектно-ориентированный подход

В ООП вы бы описали вам такие шары:

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

  void draw();
};

И тогда вы создадите коллекцию таких шаров:

vector<Ball> balls;

Ориентированный на данные подход

В Data Oriented Design, однако, вы скорее всего напишете код следующим образом:

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

  void draw();
};

Как вы можете видеть, ни одна единица не представляет одного шара больше. Объекты шара существуют неявно.

Это может иметь много преимуществ производительности. Обычно мы хотим делать операции на многих шарах одновременно. Аппаратное обеспечение обычно требует, чтобы большие непрерывные куски памяти работали эффективно.

Во-вторых, вы можете выполнять операции, которые затрагивают только часть свойств шаров. Например. если вы совмещаете цвета всех шаров различными способами, то вы хотите, чтобы ваш кеш содержал только информацию о цвете. Однако, когда все свойства шара хранятся в одном устройстве, вы также будете использовать все другие свойства мяча. Даже если они вам не нужны.

Пример использования кэша

Скажем шар, каждый шар занимает 64 байта, а точка занимает 4 байта. Кэш-память также имеет 64 байта. Если я хочу обновить положение 10 мячей, я должен вытащить 10 * 64 = 640 байт памяти в кеш и получить 10 промахов в кэше. Если, однако, я могу работать с позициями шаров в виде отдельных единиц, которые будут принимать только 4 * 10 = 40 байт. Это соответствует одной выборке кеша. Таким образом, мы получаем только 1 кеш-код, чтобы обновить все 10 мячей. Эти числа произвольны, я предполагаю, что блок кеша больше.

Но это иллюстрирует, как макет памяти может иметь серьезные последствия для кеша эффекта и, следовательно, производительность. Это будет только увеличиваться по мере увеличения разницы между ЦП и оперативной памятью.

Как разместить память

В моем примере шара я упростил проблему, потому что обычно для любого обычного приложения вы, вероятно, будете иметь доступ к нескольким переменным вместе. Например. положение и радиус, вероятно, будут использоваться вместе часто. Тогда ваша структура должна быть:

class Body {
  Point  position;
  double radius;
};

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

  void draw();
};

Причина, по которой вы должны сделать это, состоит в том, что если данные, используемые вместе, помещаются в отдельные массивы, существует риск, что они будут конкурировать за одни и те же слоты в кеше. Таким образом, погрузка одна выкинет другую.

Таким образом, по сравнению с объектно-ориентированным программированием классы, которые вы в конечном итоге делаете, не связаны с объектами в вашей ментальной модели проблемы. Поскольку данные объединены на основе использования данных, вы не всегда будете иметь разумные имена, чтобы давать свои классы в Data Oriented Design.

Отношение к реляционным базам данных

Мысль за Data Oriented Design очень похожа на то, как вы думаете о реляционных базах данных. Оптимизация реляционной базы данных может также включать использование кеша более эффективно, хотя в этом случае кеш не является кэшем кэша страниц в памяти. Хороший разработчик базы данных также, скорее всего, отделяет редко доступные данные в отдельной таблице, а не создает таблицу с огромным количеством столбцов, только когда-либо использовались только некоторые из столбцов. Он также может выбрать денормализацию некоторых таблиц, чтобы данные не могли быть доступны из нескольких мест на диске. Так же, как и с помощью Data Oriented Design, эти варианты сделаны, глядя на то, какие шаблоны доступа к данным и где узкое место производительности.

Ответ 2

Майк Актон в последнее время публично рассказал о ориентированном на данные проекте:

Мое основное изложение этого было бы: если вы хотите производительность, а затем подумайте о потоке данных, найдите слой хранения, который, скорее всего, будет винт с вами и оптимизирован для него hard. Майк фокусируется на пропуске кэша L2, потому что он делает в реальном времени, но я думаю, что то же самое относится к базам данных (чтение дисков) и даже к Web (HTTP-запросы). Я думаю, что это полезный способ программирования в системе.

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

Ответ 3

Я просто хочу отметить, что Ноэль конкретно рассказывает о некоторых конкретных потребностях, с которыми мы сталкиваемся в разработке игр. Я полагаю, что другие сектора, которые делают мягкую симуляцию в режиме реального времени, выиграют от этого, но вряд ли это будет техникой, которая продемонстрирует заметное улучшение для общих бизнес-приложений. Эта настройка предназначена для обеспечения того, чтобы каждый последний бит производительности был вытеснен из основного оборудования.

Ответ 4

Дизайн, ориентированный на данные, представляет собой конструкцию, в которой логика приложения создается из наборов данных, а не процедурных алгоритмов. Например

процедурный подход.

int animation; // this value is the animation index

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

подход к разработке данных

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();

Такие конструкции данных способствуют использованию данных для построения логики приложения. Его проще управлять особенно в видеоиграх, которые могут иметь тысячи логических путей на основе анимации или какого-то другого фактора.