Data-oriented design (DOD) focuses on how data is accessed and transformed, rather than how code is organized. This improves performance by minimizing cache misses and allowing better utilization of parallelism. The document provides an example comparing an object-oriented design (OOD) approach that stores related data together in objects, resulting in scattered memory access and many cache misses, versus a DOD approach that groups together data that is accessed together, resulting in fewer cache misses and faster performance.
In this document
Powered by AI
Introduces Data-Oriented Design (DOD), focusing on how data is read & written, and its importance.
Highlights the performance impact of data access, discussing memory latency & multithreading issues.
Describes challenges in Object-Oriented Design (OOD) like data isolation, cache misses, and optimization difficulties.
Details examples showing inefficiencies of OOD in code calls, emphasizing cache misses and performance issues.
Introduces Data-Oriented Design (DOD) concepts, focusing on output data and input needs to improve efficiency.
Presents a code example in DOD, showcasing its efficient data access and reduced memory issues.
Visual comparisons of data layouts in OOD and DOD, highlighting cache optimization implications.
Discusses the significance of optimizing for data access first, noting that many codes are memory-bound.
Focuses on real-game examples, emphasizing knowledge of data formats to optimize performance.
Compares old vs new culling systems, illustrating performance enhancements through DOD applications.
Summarizes the advantages of DOD: better performance, simpler code, and improved parallelizability.
Prompt for questions, providing links to additional resources on DOD and related topics.
Multithreading Cannot multithread without knowing how data is touched Adding locks always protects data not code Object Read? Write? Object update() Object Read? Write? Read? Write?
10.
Offloading to co-unitIf data is unknown hard/impossible to run on co-unit ? SPU/GPU/APU ?
11.
Better design Datafocus can lead to isolated, self-contained, interchangeable pieces of data and code This can make it easier to test data and code in isolation
Example - DODDesign ”back to front” and focus on the output data
29.
Example - DODDesign ”back to front” and focus on the output data Then add the minimal amount of data needed to do the transform to create the correct output
30.
Example - DODvoid 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]; } }
31.
Example - DODvoid 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]; } } What has changed?
32.
Example - DODvoid 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 What has changed?
33.
Example - DODvoid 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 What has changed?
34.
Example - DODvoid 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 What has changed?
35.
Example - DODvoid 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?
36.
Example - DODvoid 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
37.
Example - DODvoid 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]; } }
38.
Example - DODvoid 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
39.
Example - DODvoid 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
40.
Example - DODvoid 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
41.
Example - DODvoid 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 ~20 cycles
42.
Example - DODvoid 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
43.
Example - DODvoid 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
44.
Example - DODvoid 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
45.
Example - DODvoid 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
46.
Example - DODvoid 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
Example: Area Triggersposition position position position next position position position position next position position position position next Source data (Linked List)
66.
Example: Area Triggersposition 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
Links Data-Oriented Design(Or Why You Might Be Shooting Yourself in The Foot With OOP) http://gamesfromwithin.com/data-oriented-design Practical Examples in Data Oriented Design http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html The Latency Elephant http://seven-degrees-of-freedom.blogspot.com/2009/10/latency-elephant.html Pitfalls of Object Oriented Programming http://seven-degrees-of-freedom.blogspot.com/2009/12/pitfalls-of-object-oriented-programming.html Insomniac R&D http://www.insomniacgames.com/research_dev CellPerformance
77.
Image credits Catimage: http://icanhascheezburger.com/2007/06/24/uninterested-cat photo by: Arinn capped and submitted by: Andy Playstation 3 and Playstation 2 Copyright to Sony Computer Entertainment Xbox 360 Image Copyright to Microsoft “ WTF” Code quality image: Copyright by Thom Holwerda http://www.osnews.com/comics