Presentation is loading. Please wait.

Presentation is loading. Please wait.

Game Developers Conference 2009 Multithreaded AI For The Win! Orion Granatir Senior Software Engineer.

Similar presentations


Presentation on theme: "Game Developers Conference 2009 Multithreaded AI For The Win! Orion Granatir Senior Software Engineer."— Presentation transcript:

1 Game Developers Conference 2009 Multithreaded AI For The Win! Orion Granatir Senior Software Engineer

2 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

3 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

4 Multi-core Needs Parallel Applications Challenge The number of cores is increasing To really maximize performance and features, a game needs to fully utilize the CPU This means threading! GHz EraMulti-core Era APP PERFORMANCE TIME PLATFORM POTENTIAL PERFORMANCE Parallel Serial Challenge

5 Distributing work among cores means more monsters! Core Challenge

6 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

7 Game Main Loop... Let’s define a simple AI Simple AI Graphics Physics AI A simple game loop that updates in a serial manner Each AI has a state machine that makes decisions and triggers collisions and pathfinding queries as needed AI State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding

8 AI_SPAWN Let’s define some states case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } Simple AI

9 AI_IDLE Let’s define some states case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } Simple AI

10 AI_ATTACK Let’s define some states case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision:: FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } Simple AI

11 case AI_EXPLODE: { // Find a path to the player Collision::Result Result = Collision::Sphere( m_Pos ); if( Result.m_Hit ) { // Cause damage to anything near us //... } break; } AI_EXPLODE Let’s define some states Simple AI

12 AI_EXPLODE m_HP = 0 Let’s define some states // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; } Simple AI

13 Let’s put it all together Simple AI AI_IDLE AI_SPAWN AI_ATTACK AI_EXPLODE m_HP = 0 See the player Near the player

14 void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } case AI_EXPLODE: { // Cause damage to anything near us… } // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; } Let’s put it all together Simple AI

15 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

16 Process your AI in parallel Threading AI AI State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding void UpdateAI( void ) { for( int i = 0; i < g_Num_AI; i++ ) { g_AI_Array[ i ].Update(); }

17 AI State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding Use data decomposition Threading AI State Machine Collision Pathfinding State Machine Collision Pathfinding Divide the AIs into groups. This is data decomposition. void UpdateAI( void ) { for( int i = 0; i < g_Num_AI; i++ ) { g_AI_Array[ i ].Update(); }

18 AI State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding Threading AI State Machine Collision Pathfinding State Machine Collision Pathfinding Divide the AIs into groups. This is data decomposition. void UpdateAI( void ) { for( int i = 0; i < g_Num_AI; i++ ) { g_AI_Array[ i ].Update(); } Use data decomposition

19 AI Threading AI Divide the AIs into groups. This is data decomposition. Submit the AIs to a job queue or use threading API like OpenMP or Intel® Threading Building Blocks. void UpdateAI( void ) { #pragma omp parallel for for( int Index = 0; Index < g_Num_AI; Index++ ) { g_AI_Array[ Index ].Update(); } Use data decomposition State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding

20 AI Threading AI class ParallelAIContext { void operator()( const tbb::blocked_range &range ) { for(int i = range.begin(); i != range.end(); ++i) { g_AI_Array [ i ].Update(); } void UpdateAI( void ) { tbb::parallel_for( tbb::blocked_range (0, g_Num_AI), *pParallelAIContext ); } Use data decomposition Divide the AIs into groups. This is data decomposition. Submit the AIs to a job queue or use threading API like OpenMP or Intel® Threading Building Blocks. State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding State Machine Collision Pathfinding

21 There might be dragons Threading AI void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } case AI_EXPLODE: { // Cause damage to anything near us… } // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; }

22 void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } case AI_EXPLODE: { // Cause damage to anything near us… } // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; } There might be dragons What if the collision system is accessed by multiple threads? Threading AI

23 void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } case AI_EXPLODE: { // Cause damage to anything near us… } // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; } What if multiple threads are running Move? There might be dragons Threading AI

24 There might be dragons void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player EnterCriticalSection( &critical_section ); Move( Path ); LeaveCriticalSection( &critical_section ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } break; } case AI_EXPLODE: { // Cause damage to anything near us //... } //... } We could add a critical section. But this makes all AI in AI_ATTACK block on each other. Threading AI

25 Move Collision First one there wins Uses exact positions Path data is read/write First one there wins Uses positions from last frame Path data is read only, update at end of frame Processed in order Cache data Environment is read/write Serial Parallel Processed out of order Use data from last frame Environment is read only Threading AI Clearly define interactions

26 Move Collision First one there wins Uses exact positions Path data is read/write First one there wins Uses positions from last frame Path data is read only, update at end of frame Processed in order Cache data Environment is read/write Serial Parallel Processed out of order Use data from last frame Environment is read only Threading AI Clearly define interactions

27 Move Collision First one there wins Uses exact positions Path data is read/write First one there wins Uses positions from last frame Path data is read only, update at end of frame Processed in order Cache data Environment is read/write Serial Parallel Processed out of order Use data from last frame Environment is read only Threading AI Clearly define interactions

28 Let someone else worry about it! We used Havok Physics™ for Smoke to process all collisions and character movement and it’ll enforce good results. Move Collision First one there wins Uses exact positions Path data is read/write First one there wins Uses positions from last frame Path data is read only, update at end of frame Processed in order Cache data Environment is read/write Serial Parallel Processed out of order Use data from last frame Environment is read only Threading AI Clearly define interactions

29 Why deal with it? Move Collision AI If Move/Collision can update on last frame’s data… Threading AI

30 Why deal with it? Move Collision AI If Move/Collision can update on last frame’s data… Threading AI

31 Why deal with it? Move Collision AI If Move/Collision can update on last frame’s data… Threading AI

32 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

33 Getting a job in Multithread Land Multithread Land How do we get collisions running independent of AI? Issue early, use late Deferred requests Task stealing

34 void Ai::Update( void ) { switch( m_State ) { case AI_SPAWN: { // Initial Setup Setup(); m_State = AI_IDLE; break; } case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::RayCast( m_Pos, GetPlayerPos() ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } case AI_ATTACK: { // Find a path to the player Collision::Path Path = Collision::FindPath( m_Pos, GetPlayerPos() ); // Update our position to move towards the player Move( Path ); // Check if we are close to the player Vector Distance = GetPlayerPos() - m_Pos; if( Distance.Magnitude() < 1.0f ) { m_State = AI_EXPLODE; } case AI_EXPLODE: { // Cause damage to anything near us //... } // Check out hit points if( m_HitPoints == 0 ) { m_State = AI_EXPLODE; } Let’s look at collision Multithread Land

35 Issue early, use late void Ai::PreUpdate( void ) { switch( m_State ) { case AI_IDLE: { // Issue collision check m_Handle = Collision::RayCast( m_Pos, GetPlayerPos() ); break; } void Ai::Update( void ) { switch( m_State ) { case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::GetResult(m_Handle ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } // … } Block if results are not ready Multithread Land

36 Issue early, use late void UpdateAI( void ) { #pragma omp parallel for for( int Index = 0; Index < g_Num_AI; Index++ ) { g_AI_Array[ Index ].Update(); } Multithread Land

37 Issue early, use late void UpdateAI( void ) { // Process all PreUpdates #pragma omp parallel for for( int Index = 0; Index < g_Num_AI; Index++ ) { g_AI_Array[ Index ].PreUpdate(); } // Process all Updates #pragma omp parallel for for( int Index = 0; Index < g_Num_AI; Index++ ) { g_AI_Array[ Index ].Update(); } Multithread Land

38 Deferred requests void Ai::PreUpdate( void ) { switch( m_State ) { case AI_IDLE: { if( !m_Hande ) { // Issue collision check if none are pending m_Handle = Collision::RayCast( m_Pos, GetPlayerPos() ); } break; } void Ai::Update( void ) { switch( m_State ) { case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::GetResult(m_Handle ); if( Result && Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } // … } Don’t block if results are not ready… just wait until next frame Multithread Land

39 Task stealing void Ai::PreUpdate( void ) { switch( m_State ) { case AI_IDLE: { if( !m_Hande ) { // Issue collision check if none are pending m_Handle = Collision::RayCast( m_Pos, GetPlayerPos() ); } break; } void Ai::Update( void ) { switch( m_State ) { case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::GetResult(m_Handle ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } // … } If results are not ready, have this thread start processing collision request. Multithread Land

40 Task stealing void Ai::PreUpdate( void ) { switch( m_State ) { case AI_IDLE: { if( !m_Hande ) { // Issue collision check if none are pending m_Handle = Collision::RayCast( m_Pos, GetPlayerPos() ); } break; } void Ai::Update( void ) { switch( m_State ) { case AI_IDLE: { // Check is we can see the player Collision::Result Result = Collision::GetResult(m_Handle ); if( Result.m_Hit == GetPlayerID() ) { m_State = AI_ATTACK; } break; } // … } If results are not ready, have this thread start processing collision request. Multithread Land Optimizing Game Architectures with Intel Threading Building Blocks (Brad Werth) 4:30 PM – 5:30 PM in Room 2011, West Hall

41 Agenda Define a Simple AI Challenge Threading AI Working in a Multithread Land Smoke: Multithread Land Summary

42 Smoke is a Multithread Land! Smoke Framework built by Intel for N-threads Demo uses real game technologies: Havok, FMOD, Ogre3D, DX9, animation, AI, and procedural content Well partitioned and configurable

43 AI Graphics How is Smoke threaded? Framework Change Control Manager Physics Interfaces Managers Environment Platform... Scheduler Task Manager Job Pool Scheduler updates each system every frame Change Control Manager traffics changes between systems Interfaces define interaction Smoke

44 AI Graphics How is Smoke threaded? Framework Change Control Manager Physics Interfaces Managers Environment Platform... Scheduler Task Manager Job Pool Scheduler calls into each system to update Smoke

45 AI Graphics How is Smoke threaded? Framework Change Control Manager Physics Interfaces Managers Environment Platform... Scheduler Task Manager Job Pool Each system divides its work and adds jobs to the job pool The Scheduler creates one worker thread per core on the platform Smoke

46 AI Graphics How is Smoke threaded? Framework Change Control Manager Physics Interfaces Managers Environment Platform... Scheduler Task Manager Job Pool If a system makes a change that other systems need to know about, it posts that change to the Change Control Manager This allows systems to run independently Smoke

47 AI Graphics How is Smoke threaded? Framework Change Control Manager Physics Interfaces Managers Environment Platform... Scheduler Task Manager Job Pool When all the jobs are processed, the Change Control Manager distributes changes 1 2 Smoke

48 How does AI work in Smoke? AI Task Scene Object... Framework Scheduler Interfaces Object When it’s time to update the frame, the Schedule calls into the AI system and tells it to update Smoke

49 How does AI work in Smoke? AI Task Scene Object... Framework Scheduler Interfaces Object The task updates the scene by dividing all the AIs into job. These jobs are put into the job pool in the Scheduler and farmed out to worker threads. Smoke

50 How does AI work in Smoke? AI Scene Object... Framework Scheduler Interfaces Object Each Object is an AI Each AI type has a state machine Each AI can have one or more goals. Goals are shared functionality between AI types State Machine Goal... Task Smoke

51 AI How does AI work in Smoke? Object AI Objects post changes as needed. Physics wants to know about velocity changes. Graphics wants to know about position changes from Physics. State Machine Goal... Physics (Havok) Graphics (Ogre3D) Object Smoke

52 Summary Thread your AI with data decomposition To maximize AI you need to thread Design AI to work with “remote” system Download Smoke at Whatif.intel.com

53 Q/A Summary Does multithreaded AI imply non- deterministic AI? Can scripting support threaded AI? ???

54 For More Information http://www.intel.com/software/gdc Email: orion.r.granatir@intel.com See Intel at GDC: –Intel Booth at Expo, North Hall –Intel Interactive Lounge – West Hall 3 rd floor Take a collateral DVD –Here in the room! –Intel Booth or Interactive Lounge

55 Get the “Story Behind the Story” Investing in Talent and Technology See What’s New Developers Connecting with Intel Engineers Training the Next Generation Enhance Your Products and Your Business The gateway to Intel’s worldwide technology, engineering and go-to-market support for Visual Computing developers www.intel.com/software/visualadrenaline

56 Intel @ GDC Wednesday, March 25 –Intel’s New Graphics Performance Analyzers 2:30 PM – 3:30 PM in Room 3004, West Hall –Kaboom: Real-Time Multi-Threaded Fluid Simulation for Games 4:00 PM – 5:00 PM in Room 2011, West Hall

57 More Intel @ GDC Thursday, March 26 –Who Moved the Goalposts? The Rapidly Changing World of CPU’s and Optimization 1:30 PM – 2:30 PM in Room 2011, West Hall –Taming Your Game Production Demons: the Offset approach 3:00 PM – 4:00 PM in Room 2011, West Hall –Optimizing Game Architectures with Intel Threading Building Blocks 4:30 PM – 5:30 PM in Room 2011, West Hall

58 Last of Intel @ GDC Friday, March 27 –Procedural and Multi-Core Techniques to take Visuals to the Next Level 9:00 AM – 10:00 AM in Room 2010, West Hall –Rasterization on Larrabee: A First Look at the Larrabee New Instructions (LRBni) in Action 9:00 AM – 10:00 AM in Room 135, North Hall –SIMD Programming on Larrabee: A Second Look at the Larrabee New Instructions (LRBni) in Action 10:30 AM – 11:30 AM in Room 3002, West Hall

59  INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL® PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL’S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER, AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL® PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT. INTEL PRODUCTS ARE NOT INTENDED FOR USE IN MEDICAL, LIFE SAVING, OR LIFE SUSTAINING APPLICATIONS.  Intel may make changes to specifications and product descriptions at any time, without notice.  All products, dates, and figures specified are preliminary based on current expectations, and are subject to change without notice.  Intel, processors, chipsets, and desktop boards may contain design defects or errors known as errata, which may cause the product to deviate from published specifications. Current characterized errata are available on request.  Performance tests and ratings are measured using specific computer systems and/or components and reflect the approximate performance of Intel products as measured by those tests. Any difference in system hardware or software design or configuration may affect actual performance.  Intel, Intel Inside, and the Intel logo are trademarks of Intel Corporation in the United States and other countries.  *Other names and brands may be claimed as the property of others.  Copyright © 2009 Intel Corporation. Legal Disclaimer

60 Risk Factors This presentation contains forward-looking statements. All statements made that are not historical facts are subject to a number of risks and uncertainties, and actual results may differ materially. Please refer to our most recent Earnings Release and our most recent Form 10-Q or 10-K filing available on our website for more information on the risk factors that could cause actual results to differ.


Download ppt "Game Developers Conference 2009 Multithreaded AI For The Win! Orion Granatir Senior Software Engineer."

Similar presentations


Ads by Google