Optimizing Code using Unity's C# Job System (Tech Demo)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

I really wish you will show us how the new ecs system works with a simple game example! Knowing how well you know this subject I know for sure it will be infaillible! (see what I did there)

👍︎︎ 6 👤︎︎ u/DoucheMcAwesome 📅︎︎ Mar 05 2018 🗫︎ replies

The Job dependency seems extremely bizarre. Are you sure it wasn't because you're kicking off and wait for completion between jobs?

Traditional threading experience would suggest you'd want to kick off all the jobs then wait for completions. Can someone with the beta look into this?

👍︎︎ 3 👤︎︎ u/jayd16 📅︎︎ Mar 05 2018 🗫︎ replies

A lot of thanks. Now I understand better unity jobs. Well explained 👏🏻

👍︎︎ 1 👤︎︎ u/Black_malzar 📅︎︎ Mar 05 2018 🗫︎ replies
Captions
I've been watching out for unities new c-sharp job system ever since that cool tech demo last year at unite Europe I signed up for the beta program and never heard back but it's all good because in the 2018 point one beta we finally have access in this video we're gonna take a look at an ocean simulation that I created using mesh deformations and we're gonna put the Java system to the test to see if we can squeeze out any performance from some really under performant code but before we get into the code let's run the simulation and look at the profiler feel that ocean breeze hey somebody get me a pina colada yeah okay back to reality let's stop the profiler on a random frame see what kind of performance we're getting so it looks like each frame is taking about 40 milliseconds well I guess that's not bad considering my prehistoric CPU and what we're doing here but I think we can do better it looks like the update method of the simulation script is taking up most of the frame what could it possibly be doing well let's find out like I mentioned before those gentle ocean waves are achieved through mesh deformation so the first thing update does is grab a copy of the ocean meshes vertices then it flattens them a resetting the y-value of each vertex and applies Perlin noise using a list of Perlin noise layers that are created via the editor oh wait say what yeah this script deforms a mesh using layers of pearl and noise that are defined by the designer each layer contains scale speed and height properties that are applied to the Pearl annoys function for this demonstration I've added four layers of perla noise so what happens in the code for each layer the logic can be found encapsulated within AD Perlin noise layer basically it loops through each vertex and uses the Perlin noise layer object and math F dot Perlin noise to calculate a value for y now might be a good time to mention that the ocean mesh contains 65,536 vertices now multiply that by four layers and you've got 260 mm 144 iterations ouch that's a lot of iterations if only there was some way to split this four loop into bite-sized pieces and then run each piece simultaneously using all of the cores in my processor enter unities new c-sharp job system starting in unity 20 18.1 which is currently in beta we'll have access to a new high-performance multi-threaded system which will make it possible to take advantage of multi-core processors now there currently isn't much in the way of documentation but lucky for you I've been watching videos poking around the code and banging my head against the wall also I could create a small technical demo to show off what some of the code actually looks like so without further ado let's create a job the first thing you need to know is that jobs are required to be strux rather than classes classes take longer to access a memory and the name of the game is optimization right secondly each of your jobs must implement one of three types I job i job parallel for or I job parallel for transform in this case I'm going to use i job parallel for because our job needs to run a single task many times in parallel before we write the execute logic let's give the job access to the vertices through a public member variable that will set before we schedule the job one of the features of unity c-sharp job system is native containers will store our vertices than a native container called native array the reason for this is that we want to have complete control over the allocation and de-allocation of memory which native containers allow us to do we'll see that in action soon next we need to add a new field for layer settings as well as one for time now we can copy and paste the contents of our unoptimized for loop into the execute method of our job I'll just quickly clean this up using resharper all right now we can schedule the job and see it in action in order to compare the before and after results of the optimization I'm going to add a boolean that a little toggle between the old logic and the new job system and I'm going to encapsulate the new logic within its own method so the code will be easier to follow along all right first things first we'll need to loop through our layers for each layer we're going to need to instantiate a new instance of Perlin noise layer job then we'll need to populate the jobs member variables I'm going to instantiate a new native array to hold the vertices remember this native container gives us complete control over the allocation and de-allocation of memory for our data by instantiating native array were implicitly allocating space in memory and likewise we'll need to explicitly deallocate that space when the job is complete with our jobs dependencies now filled we're ready to kick it off by calling schedule we'll use the length of the vertex array tell the job how many records it needs to process and a hard-coded value for how many records to process in each batch let's say 250 records per batch this causes the job to start running asynchronously on multiple threads and that's great in theory but there's one side effect that we need to deal with once the job is begun we don't really know when it'll end that won't work for us though because in this case we need to be sure that our jobs finish their work during the same frame that they were kicked off well luckily for us the scheduled method returns an instance of the job handle class that we can use to ensure that each job is completed before moving on it's as simple as calling job handle dot complete and that's it now that we know that the job is completed we can copy the values from the native array back into vertices and then deallocate the memory by calling vertex array dot dispose let's run this and check the profiler for any performance gains ouch looks like we actually lost performance our frames are taking even longer to render what gives let's take a look at the unity job system section which seems to have entries that weren't there before that's interesting we can see that the jobs are running and they're doing so asynchronously but what's up with these gaps we're losing a lot of time to these three millisecond periods between each job well looks like we're gonna need to get back to the old drawing board well you're not I am in fact I've already looked into this and the answer seems to lie in stringing each job along as a dependency of the job that comes after it let me break it down for you first I'm gonna get rid of this loop temporarily and we'll just focus on two layers so there's job one handling the first layer now let's add job two to handle the second layer now the difference here is that when we scheduled job two we need to pass in job handle one as a dependency this will cause job two to wait for job one to complete when job one is done job two will kick off immediately in other words no more gaps here let me show you take a look at the worker threads they bump up right against each other which is exactly what we were looking for now we can reimplementation Alyss to hold them for each iteration we'll create a job scheduled it and add the resulting job handle to the list for scheduling we'll need to check the list and use the preceding job handle as a dependency for the current job unless this is the first iteration now all we have to do is call complete on the last job handle the job system is smart enough to traverse through the list of dependencies and start processing the jobs at the route all right let's run it again and check the profiler so currently each frame takes about 40 milliseconds to process now let's talk with the job system whoa check out that improvement the frame rates still a little rough but at least the CPU isn't working nearly as hard as it was before let's add a couple more layers and see what happens we can see that using the job system adding more layers skills much better whereas without it it doesn't scale at all Bernie interesting stuff so that was my first stab at unities new C sharp job system if you'd like access to the code please consider supporting me on patreon for $5 to get access to all the codes showing off in this video and in my other videos as well I've even thrown in a bonus project that uses the job system to do some audio visualization it's pretty cool you should check it out if you enjoyed this video please leave a like and a comment letting me know what you thought and for more unity tutorials just like this one please subscribe with notifications on see in the next video thank you to all my supporters on patreon and a special shout-out to our star Jakov and DiLeo [Music] [Applause]
Info
Channel: Infallible Code
Views: 78,523
Rating: undefined out of 5
Keywords: unity c# job system, unity job system, c# job system, c# job system unity, unity 2018, job system unity, unity job system preview, unity job system 2018
Id: gibqhg0wMA0
Channel Id: undefined
Length: 12min 41sec (761 seconds)
Published: Mon Mar 05 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.