Data-oriented design in game development Johannes Hirche - - PowerPoint PPT Presentation

data oriented design in game development
SMART_READER_LITE
LIVE PREVIEW

Data-oriented design in game development Johannes Hirche - - PowerPoint PPT Presentation

Data-oriented design in game development Johannes Hirche Introduction (Most) video games present a number of challenges Soft real time >30Hz Large amount of data Up to 2 billion polygons/s Tenths of thousands of objects


slide-1
SLIDE 1

Data-oriented design in game development

Johannes Hirche

slide-2
SLIDE 2

Introduction

(Most) video games present a number of challenges

  • Soft real time

– >30Hz

  • Large amount of data

– Up to 2 billion polygons/s – Tenths of thousands of objects – Gigabytes of textures (image data) – Physics simulations

slide-3
SLIDE 3

Introduction

  • Highly dynamic

– Depending on user input – Network (user input as well)

  • Can’t be solved by throwing new

hardware at it

– Clients not likely to have the newest things available – Consoles have fixed performance

slide-4
SLIDE 4

Obvious conclusion

  • Processing needs to be as efficient as

possible

slide-5
SLIDE 5

Main Bottleneck

  • Memory throughput and access time
slide-6
SLIDE 6

How bad is it really?

PlayStation 2

  • A read from memory takes 40 cycles at

300 MHz PlayStation 3 + Xbox 360 + Fast PC

  • A read from memory takes ~600 cycles

at 3.2 GHz

slide-7
SLIDE 7

Memory Latency Hierarchy

Disks (Blu-ray/DVD/HDD) Main Memory L2 Cache L1 Cache CPU / Registers Latency :( 40 cycles 1 – 2 cycles 600 cycles

slide-8
SLIDE 8

And it won’t get better anytime soon

slide-9
SLIDE 9

Next conclusion

  • Reduce data?

– Not really an option

  • Focus on memory performance is key
slide-10
SLIDE 10

Impact on Video Game Industry

Last few years shift in focus in design

  • Away from object oriented design to

more C-like style

  • “Data-Oriented Design” emerged
slide-11
SLIDE 11

So what is this Data-Oriented Design?

slide-12
SLIDE 12

It’s about on shifting focus to how data is read and written

You cannot be fast without knowing how data is touched

slide-13
SLIDE 13

Data Oriented Design – Example

class Bot { ... Vec3 m_position; ... float m_mod; ... float m_aimDirection; ... void updateAim(Vec3 target) { m_aimDirection = dot3(m_position, target) * m_mod; } }

slide-14
SLIDE 14

Data Oriented Design – Example

class Bot { ... Vec3 m_position; ... float m_mod; ... float m_aimDirection; ... void updateAim(Vec3 target) { m_aimDirection = dot3(m_position, target) * m_mod; } }

I-cache- miss D-cache- miss Unused cached data

slide-15
SLIDE 15

Data Oriented Design – Example

class Bot { ... Vec3 m_position; ... float m_mod; ... float m_aimDirection; ... void updateAim(Vec3 target) { m_aimDirection = dot3(m_position, target) * m_mod; } }

I-cache- miss D-cache- miss Unused cached data

Very hard to optimize!

slide-16
SLIDE 16

void updateAim(Vec3 target) { m_aimDirection = dot3(m_position, target) * m_mod; }

Assume we have four different bots

iCache – 600 m_position – 600 m_mod - 600 aimDir – 100 ~20 cycles iCache – 600 m_position – 600 m_mod - 600 aimDir – 100 iCache – 600 m_position – 600 m_mod - 600 aimDir – 100 iCache – 600 m_position – 600 m_mod - 600 aimDir – 100

7680

Data Oriented Design – Example

slide-17
SLIDE 17

What to do??

  • Isolate task at hand

– Arrange for many at once

  • Find the data objects
  • Design based on access patterns
  • Focus on output data
  • Only read in data really necessary to

do the work!

  • Linear arrays!
slide-18
SLIDE 18

void updateAims(float* aimDir,const AimingData* aim, Vec3 target, uint count) { for (uint i = 0; i < count; ++i) { aimDir[i] = dot3(aim->positions[i],target) * aim->mod[i]; } }

Only ¡read ¡needed ¡inputs Write ¡to ¡linear ¡array Loop ¡over ¡all ¡the ¡data Actual ¡code ¡unchanged

What has changed?

Code ¡separated Data Oriented Design – Example

slide-19
SLIDE 19

void updateAims(float* aimDir, const AimingData* aim, Vec3 target, uint count) { for (uint i = 0; i < count; ++i) { aimDir[i] = dot3(aim->positions[i], target) * aim->mod[i]; } }

iCache – 600 positions – 600 mod - 600 aimDir – 100 ~20 cycles 1980

Data Oriented Design – Example improved

slide-20
SLIDE 20

pos0 mod0

aimDir0

pos0 Pos1 Pos1 Pos1 Pos1 mod1 aimDir 1 pos0 pos0 pos0 pos1 pos1 pos1 pos1 pos2 pos2 pos2 pos2 pos3 pos3 pos3 pos3 mod0 mod1 mod2 mod3

aimDir0 aimDir1 aimDir2 aimDir3

pos0 pos0 pos0

Each color block is one 128 byte cache line

Data Layout OO vs DOD

slide-21
SLIDE 21

Put into one sentence

Scrap objects and put everything in linear arrays!

slide-22
SLIDE 22

Other Benefits

slide-23
SLIDE 23

Multithreading / Parallelization

Object

Read? Write?

Object Object

Read? Write? Read? Write?

Update()

slide-24
SLIDE 24

Multithreading / Parallelization

  • Cannot multithread without knowing how

data is touched

Object

Read? Write?

Object Object

Read? Write? Read? Write?

Update()

slide-25
SLIDE 25

Multithreading / Parallelization

  • Object focused design harder to do parallel

– Large overhead for synchronization

  • Locks, mutexes, etc.

– Very error-prone, hard to debug – Maybe slower than single thread in the end

slide-26
SLIDE 26

Multithreading / Parallelization

The future is parallel!

  • No way to avoid multiple cores

DoD is easier to parallelize

  • We have:

– Input data – Small function processing it – Output data

  • Can be split easily
slide-27
SLIDE 27

Cache Utilization

  • Better usage of instruction cache
  • Processed data sits linearly in memory

– Almost perfect usage of data cache

slide-28
SLIDE 28

Why – Offloading to Co-Processors

  • If data is unknown hard/impossible to

run on co-unit

? SPU/GPU/APU ?

slide-29
SLIDE 29

DOD Code is more modular, easier to optimize!

  • Big chunk of data to transform
  • One isolated function processes whole

block

– Modular code

  • Optimize the function by whatever means

– Assembler etc. – Still readable, manageable – Big performance gain!

slide-30
SLIDE 30

DOD Code is easier to test!

  • Functionality is in one function with one

in and output

  • Easier to generate stream of data with

test cases

– Compare results

  • Perfect for unit tests
slide-31
SLIDE 31

Why – Better Design… at least sometimes

  • Data focus can lead to isolated, self-

contained, interchangeable pieces of code and data

  • Object focus can lead to framework hell

WindowBorderDecoratorAccessorIterator….

slide-32
SLIDE 32

Why – Better Design… at least sometimes

  • Data focus can lead to isolated, self-

contained, interchangeable pieces of code and data

  • This can make it easier to test data and code

in isolation

slide-33
SLIDE 33

Performance is all about memory!

  • Optimize for data first then code

– Classic approach is to meddle with code

  • Most code likely bound by memory access
  • Not everything needs to be an object
  • We do games, we know our data!
  • Pre-format!

– Source data and native data doesn’t need to be the same

slide-34
SLIDE 34

position position position position next position position position position next position position position position next

Source data (Linked List) Native Data (Array)

position position position position position position position position position position position position position position count

Performance is all about memory!

slide-35
SLIDE 35

DOD Drawbacks?

  • Many people are OO-minded

– Need to realign the brain a bit

  • Can be hard to interface with legacy

OO code

slide-36
SLIDE 36

How to actually do it

  • Pick specific section of your project

– Navigation, collision, animation etc

  • Find data inputs, identify required outputs

– Collision creates set of contact points etc.

  • Classify the data

– Read-only, read-write, write-only – Defines where to store and how to interact with other modules

slide-37
SLIDE 37

How to actually do it

  • Find data required to do many

transforms at once

– Not one skeleton, hundreds

  • Determine how data is used

– Try to store same data in blocks for seperate processing

slide-38
SLIDE 38

So OO is dead in game development?

  • OO still works if there are few or single

instances with functionality

– GraphicsDevice

  • GUI code not performance critical

– OO works fine there – Legacy code usually OO anyway

slide-39
SLIDE 39

Some provocative statements about

  • bject oriented design
slide-40
SLIDE 40

Some C++ History

  • 1979 Development started
  • 1983 Named ‘C++’
  • 1985 First commercial release
  • 1989 Release 2.0
  • 1998 Standardized
  • 2003 + 2011 updated
slide-41
SLIDE 41

Let’s look back at 1979…

slide-42
SLIDE 42

A LOT has changed since then

  • CPUs have become MUCH faster
  • Memory has become a little faster
  • Multiple cores
  • Lots of things have been added to C++
slide-43
SLIDE 43

Visions/Goals with OO

  • Reusable code classes!

– Didn't really work out – Had to become super configurable to actually be useful

  • Great design pattern!

– Overuse of design patters results in overly complex code – Better to write code in a model you understand and not in some abstract way someone else came up with

slide-44
SLIDE 44

Visions/Goals with OO

  • Frameworks for classes and components

are great!

– Idea: Hide all implementation and technical complexity – Too restrictive, cumbersome and too much work

slide-45
SLIDE 45

Visions/Goals with OO

  • Inheritance! Interfaces!

– Identify common code/behavior and put in shared base class! No duplicated code, benefits! – In practice not really. Every subclass needs minor adaptations. – Changing the base class will break everything – Often only used for interfaces

slide-46
SLIDE 46

Visions/Goals with OO

  • Encapsulation!

– Encapsulate state and variables, only expose behavior with functions. – In reality you often enough you want the values of variables – Why not just use a normal struct or structured data

slide-47
SLIDE 47

The Three Big Lies

  • 1. Software is a platform
  • 2. Code should be designed around a

model of the world

  • 3. Code is more important than data
slide-48
SLIDE 48

Questions?