程序代写代做代考 compiler chain cache c# Squishy Maps for Soft Body Modelling Using Generalised Chain Mail

Squishy Maps for Soft Body Modelling Using Generalised Chain Mail

KIT308/408 (Advanced) Multicore Architecture and Programming

Unity DOTS
Dr. Ian Lewis
Discipline of ICT, School of TED
University of Tasmania, Australia
1

Multiple systems
Slogan “Performance by default”
Main idea “…is to take advantage of the CPU’s cache and your GPU’s SIMD capabilities to achieve incredible performance output”
Sound familiar?
Important ones for today
ECS
Entity–Component System
Job System
Burst Compiler
Just trying to give you the flavour of this kind of thing
To see that the techniques we’ve used in this unit have “real-world” analogues

2
Unity Data-Oriented Technology Stack
The content for these slides is heavily lifted from a 3-part series on Medium
https://medium.com/@nikolay.karagyozov1/getting-started-with-unity-dots-part-1-ecs-7f963777db8e
https://medium.com/@nikolay.karagyozov1/getting-started-with-unity-dots-part-2-c-job-system-6f316aa05437
https://medium.com/@nikolay.karagyozov1/getting-started-with-unity-dots-part-3-burst-compiler-7d639274ca1e
And some from this Unity tech talk:

When needing to solve a specific problem or bypassing a technical hurdle
e.g. too many spawned objects makes the game hitch
Can be implemented incrementally
Can have only parts of the game implemented using DOTS
Pay attention to the roadmap, because this is all still a little experimental

3
When to use DOTS

Unity Entity–Component System
Unity DOTS

4

Normal Unity GameObject memory layout
This is basically AoS

5
Unity ECS Memory Layout
Unity ECS memory layout
This is basically SoA

Want to combine like concepts into single list of values
So here
Speed
Health
Rigidbody

6
How to Structure Data

Want to combine like concepts into single operation
So here
Update direction
Update position in world

7
How to Structure Functionality

Entity
Like a GameObject substitute, built around a “where there is on there is many” idea
Component
Not the usual Unity component
Models the data that will be processed
System
Systems are scripts that read component data and compute the next state

8
Unity ECS

In this example, we have 3 entities in our world: A, B, and C
The flow can be described like this
A system fetches all translation and rotation components in our world
It performs calculations in bulk
Finally, it writes the output result back to all of the fetched entities

9
Unity ECS

System calculation
T is an array of all translations
R is an array of all rotations
T * R is performed for all indexes of the “list”

10
Unity ECS

In this example
A and B have a Renderer component
C doesn’t
ECS “collects” needed entity data before doing the calculation
Can filter how ever you want
e.g. just get all entities with Renderer

11
Unity ECS

Unity groups like ECS entities into archetypes
For performance
You can add / remove components from entities at runtime
Changes their archetype

12
Unity ECS Archetypes

Archetypes allow for memory chunking
Every chunk contains multiple entities of the same archetype
It’s a bit AoSoA

13
Unity ECS Archetypes

Entities are created by an EntityManager
Which is responsible for maintaining a list of all entities and organising data for speed
CreateEntity can create an entity from
Array of components
EntityArchetype
Existing Entity

14
ECS Entities

Ran out of time to finish presentation 🙁

15
[Insert missing slides here]

Can use Convert to tell ECS to make “copies” of the data
public void Convert(Entity entity, EntityManager manager, GameObjectConversionSystem conversion)
{
manager.AddComponent(entity, typeof(whatever)

manager
manager.AddComponentData(entity,
}

16
Converting GameObjects to ECS Entities

Entities.ForEach((ref A outputComponent, in B readComponent) => { … });

17
Entity ForEach

[WriteGroup(SoldierHealth)]
public struct DoubleHealthRegenBuff : IComponentData { … }
public struct SoldierHealth : IComponentData { … }

// NormalHealthRegenSystem.cs:

Entities.WithEntityQueryOptions(EntityQueryOptions.FilterWriteGroup)
.ForEach((ref SoldierHealth health) => {
// compute health regen at 1x speed
}).ScheduleParallel();

18
Calling ECS Queries

Unity Job System
Unity DOTS

19

The Job System helps create multithreaded code
Via the creation of jobs, not threads
A job is small unit of work
Does something specific
Gets parameters
Operates on data
The Job System manages a pool of worker threads across many cores
Usually one worker per logical core

20
Unity Job System

All jobs are put in the job queue
Worker threads then pick jobs from the queue
Some jobs might have dependencies (on other jobs)
The Job System makes sure everything happens in the correct order

21
Unity Job System Scheduling

Managed vs Unmanaged memory
i.e. garbage collected or not
Blittable types
Same memory layout in managed and unmanaged code
Race condition safety
Jobs always work with copies of the original data
Copying data from managed to unmanaged memory

22
Unity Job System Memory

Native containers work on pointers to unmanaged memory
NativeArray, NativeList, NativeHashMap, NativeMultiHashMap, NativeQueue
When creating these you specify an allocator
Temp
Exists for 1 frame
TempJob
Exists for 4 frames
Persistent
Last forever, but slower

23
Unity Job System Native Containers
NativeArray arr =
new NativeArray
(1, Allocator.TempJob);

To create a job:
Create a struct that implements Ijob
Add member variables
Blittable types or native containers
Implement Execute()

24
Creating Jobs
public struct AddJob : IJob
{
public float a;
public float b;
public NativeArray result;

public void Execute()
{
result[0] = a + b;
}
}

To schedule a job:
Instantiate the job
Populate its data
Call Schedule() from the main thread

25
Scheduling Jobs
var result = new NativeArray(1,
Allocator.TempJob);

var job = new AddJob();
job.a = 10;
job.b = 20;
job.result = result;

JobHandle handle = jobData.Schedule();

// Wait for the job to complete
handle.Complete();

// get result
float aPlusB = result[0];

// clean up
result.Dispose();

Dependencies
ParallelFor jobs
Job Design Patterns

26
Topics We Didn’t Cover

Unity Burst Compiler
Unity DOTS

27

C# traditionally compiles to IL / .NET bytecode
Which is then interpreted (or compiled Just-In-Time)
Although Unity also uses IL2CPP to try and increase efficiency
Burst uses LLVM
So does Swift, Rust, Kotlin Native, etc.
Burst compiles jobs to improve performance

28
Burst Compiler

Burst is very good at optimising math from Unity.Mathematics
Using SIMD operations
The compiler does this, not the programmer

29
SIMD

Just need to an attribute to a job
Magic!

30
Using Burst
[BurstCompile]
struct ExampleJob : IJob { … }

Lots of support for this “magic”
Can use structs and value types
Built for ECS
Support for generics
Can throw exceptions (but only in the editor)
Speed

31
Burst Features

Magic does work for everything
Can’t use reference types
e.g. classes, strings, etc.
Can’t access GameObject / Component code
Can’t write to static variables
No support for catching exceptions (try/catch)
So got

32
Burst Limitations

Use this when you have existing code that still uses GameObjects / classes and still want to use Burst for some parts
You create a job that would execute your logic
You create a struct that holds only the data you need for the job and strips away everything else that is unnecessary
Copy the data into the new struct
Pass the struct as job parameter
Schedule the job
Burst compiles it
Save the job result it a native container
Copy the native container back to the original classes

33
Copy/Burst/Copy Design Pattern

public List GetData() {

}

public Vector3 IntensiveCalculation(
List values) {
for (int i=0; i < values.Count; i++) { values[i].position = Vector3.zero; } } ... // in Update() var data = GetData(); IntensiveCalculation(data); [BurstCompile] struct ExampleJob : Ijob { public NativeArray Data;
public void Execute() {
for (int i=0; i GetData() { … }

34
Copy/Burst/Copy Example: Part 1

public List GetData() {

}

public Vector3 IntensiveCalculation(
List values) {
for (int i=0; i < values.Count; i++) { values[i].position = Vector3.zero; } } ... // in Update() var data = GetData(); IntensiveCalculation(data); // in Update() var data = GetData(); var jobData = new NativeArray(data.Count, Allocator.TempJob);
// Copy
for (int = 0; i < jobData.Length; i++) { jobData[i].position = data[i].position } // Burst var job = new ExampleJob { Data = jobData } job.Run(); // Copy for (int = 0; i < jobData.Length; i++) { data[i].position = jobData[i].position } 35 Copy/Burst/Copy Example: Part 2 Burst uses NativeArray So need to treat 2D (or higher) arrays as 1D ones 36 Using NativeArray var matrix = new int[height, width]; ... matrix[x, y] = ...; Becomes: var matrix = new NativeArray(
height * width,
Allocator.Persistent
);

matrix[x * height + y] = …;

Floating-point calculation mode
Strict
Don’t do weird things
Fast
Do all the weird things
e.g. y/x -> 1/x * y

37
Burst Compiler Options: FloatMode
[BurstCompile(FloatMode = FloatMode.Fast]
struct ExampleJob : IJob { … }

Floating-point precision mode
Medium
3.5 ULP accuracy
High
1 ULP accuracy
ULP = unit of least precision
The difference between two consecutive floating-point numbers is equal to 1 ULP

38
Burst Compiler Options: FloatPrecision
[BurstCompile(FloatPrecision =
FloatPrecision.Medium]
struct ExampleJob : IJob { … }