The Next Mainstream Programming Language: A Game Developers Perspective - PowerPoint PPT Presentation

1 / 67
About This Presentation
Title:

The Next Mainstream Programming Language: A Game Developers Perspective

Description:

Crossbow. Generic Game Framework. Game-Specific Framework Extension ... How might this work? Good ideas, though they make the compiler's job significantly harder... – PowerPoint PPT presentation

Number of Views:118
Avg rating:3.0/5.0
Slides: 68
Provided by: nsh
Category:

less

Transcript and Presenter's Notes

Title: The Next Mainstream Programming Language: A Game Developers Perspective


1
The Next Mainstream Programming Language A Game
Developers Perspective
  • By Tim Sweeney
  • Presented by Katie Coons

2
Outline
  • Whats in a game?
  • Game simulation
  • Numeric computation
  • Shading
  • Programming language requirements
  • Modularity
  • Concurrency
  • Reliability
  • Performance

3
Whats in a game?
Productivity is very important. Think
reliability.
  • Resources
  • 10 programmers
  • 20 artists
  • 24 month development cycle
  • 10M budget
  • Software Dependencies
  • 1 middleware game engine
  • 20 middleware libraries
  • OS graphics APIs, sound, input, etc.

Modularity is important.
4
Software Dependencies
Gears of War Gameplay Code250,000 lines C,
script code
Unreal Engine 3 Middleware Game Engine 250,000
lines C code
DirectX Graphics
OpenAL Audio
OggVorbis Music Codec
Speex SpeechCodec
wxWidgets Window Library
ZLib Data Compr- ession

5
Outline
  • Whats in a game?
  • Game simulation
  • Numeric computation
  • Shading
  • Programming language requirements
  • Modularity
  • Concurrency
  • Reliability
  • Performance

6
Gameplay Simulation
7
Gameplay Simulation
  • Models state of the game world as interacting
    objects evolve over time
  • High-level, object-oriented code
  • C or scripting language
  • Imperative programming
  • Usually garbage-collected

Mutable state - synchronization and concurrency
are hard.
8
Gameplay Simulation
  • 30-60 updates (frames) per second
  • 1000 distinct gameplay classes
  • Contain imperative state
  • Contain member functions
  • Highly dynamic
  • 10,000 active gameplay objects
  • Each time a gameplay object is updated, it
    typically touches 5-10 other objects

This is a lot of mutable state to keep track of,
and it changes very frequently.
9
Numeric Computation
10
Numeric Computation
  • Algorithms
  • Scene graph traversal
  • Physics simulation
  • Collision Detection
  • Path Finding
  • Sound Propagation
  • Low-level, high-performance code
  • C with SIMD intrinsics
  • Essentially functional

Potential concurrency to exploit
11
Shading
12
Shading
  • Generates pixel and vertex attributes
  • Written in HLSL/CG shading language
  • Runs on the GPU
  • Inherently data-parallel
  • Control flow is statically known
  • Embarassingly Parallel
  • Current GPUs are 16-wide to 48-wide!
  • What lessons can we learn from shading languages?
  • Do we want a language that exploits this data
    parallelism as well as fine and course grained
    thread/task parallelism?

13
Shading
  • Game runs at 30 FPS _at_ 1280x720p
  • 5,000 visible objects
  • 10M pixels rendered per frame
  • Per-pixel lighting and shadowing requires
    multiple rendering passes per object and per
    light
  • Typical pixel shader is 100 instructions long
  • Shader FPUs are 4-wide SIMD
  • 500 GFLOPS compute power
  • Great results, but with special
    hardware/software.
  • How well do these abilities map to other
    problems?
  • Is a hybrid approach worth trying?

14
Three Kinds of Code
15
Three Kinds of Code
Maybe we can increase these with a little extra
concurrency?
16
Outline
  • Whats in a game?
  • Game simulation
  • Numeric computation
  • Shading
  • Programming language requirements
  • Modularity
  • Concurrency
  • Reliability
  • Performance

17
The hard problems according to Tim Sweeney
  • Modularity
  • Very important with 10-20 middleware libraries
    per game
  • Concurrency
  • Hardware supports 6-8 threads
  • C is ill-equipped for concurrency
  • Reliability
  • Error-prone language / type system leads to
    wasted effort finding trivial bugs
  • Significantly impacts productivity
  • Performance
  • When updating 10,000 objects at 60 FPS,
    everything is performance-sensitive

These are all very strongly connected
18
Modularity
19
Game Class Hierarchy
Generic Game Framework
Actor Player Enemy
InventoryItem Weapon
Game-Specific Framework Extension
Actor Player Enemy Dragon
Troll InventoryItem Weapon
Sword Crossbow
20
Game Class Hierarchy
Generic Game Framework
Actor Player Enemy
InventoryItem Weapon
Game-Specific Framework Extension
Actor Player Enemy Dragon
Troll InventoryItem Weapon
Sword Crossbow
What if we want to extend the base class?
21
Software Frameworks
  • The Problem Users of a framework want to
    extend the functionality of the frameworks
    base classes!
  • The workarounds
  • Modify the source and modify it again with
    each new version
  • Add references to payload classes, and
    dynamically cast them at runtime to the
    appropriate types.
  • Maybe the compiler could help us

Error prone!
Ugly, and runtime casting can be error-prone
22
A Better Solution
Base Framework
Extended Framework
package Engine class Actor int
Health class Player extends
Actor class Inventory extends Actor
Package GearsOfWar extends Engine class Actor
extends Engine.Actor // Here we can add new
members // to the base class. class Player
extends Engine.Player // Thus virtually
inherits from // GearsOfWar.Actor class Gun
extends GearsOfWar.Inventory
The basic goalTo extend an entire software
frameworks class hierarchy in parallel, in an
open-world system.
Definitely applicable to non-graphics tasks, as
well
23
A Better Solution
Base Framework
Extended Framework
package Engine class Actor int
Health class Player extends
Actor class Inventory extends Actor
Package GearsOfWar extends Engine class Actor
extends Engine.Actor // Here we can add new
members // to the base class. class Player
extends Engine.Player // Thus virtually
inherits from // GearsOfWar.Actor class Gun
extends GearsOfWar.Inventory
Why dont we do this already?
Multiple inheritance? Type system implications?
24
Concurrency
25
The C/Java/C ModelShared state concurrency
  • The Idea
  • Any thread can modify any state at any time.
  • All synchronization is explicit, manual.
  • No compile-time verification of correctness
    properties
  • Deadlock-free
  • Race-free

With current constructs, the compiler cant do
this
26
The C/Java/C ModelShared state concurrency
  • This is hard!
  • Possible workarounds
  • 1 main thread responsible for doing work that
    isnt safe to multithread
  • 1 heavyweight rendering thread
  • A pool of 4-6 helper threads
  • Dynamically allocate them to simple tasks.
  • Program Very Carefully!
  • Huge productivity burden
  • Scales poorly to thread counts

We could better exploit this concurrency
There must be a better way!
27
Three Kinds of Code Revisited
  • Shading
  • Already implicitly data parallel
  • Numeric Computation
  • Computations are purely functional
  • But they use state locally during computations
  • Gameplay Simulation
  • Gratuitous use of mutable state
  • 10,000s of objects must be updated
  • Typical object update touches 5-10 other objects

28
Concurrency in Shading
  • Look at the solution of CG/HLSL
  • New programming language aimed at Embarrassingly
    Parallel shader programming
  • Its constructs map naturally to a data-parallel
    implementation
  • Static control flow (conditionals supported via
    masking)

29
Concurrency in Shading
  • Conclusion The problem of data-parallel
    concurrency is effectively solved(!)
  • Proof Xbox 360 games are running with 48-wide
    data shader programs utilizing half a Teraflop of
    compute power...

30
Referential Transparency
  • Any subexpression can be substituted with its
    value at any time
  • without changing the meaning of the program.
  • Advantages
  • Static analysis is easier
  • Automatic code transformations easier
    (memoization, CSE)
  • Easier to prove correctness
  • Opportunities for concurrency

?
?
A 1 (34) A 1 12
A GetInput()
31
Concurrency in Numeric Computation
  • These are essentially pure functional algorithms,
    but they operate locally on mutable state
  • Haskell ST, STRef solution enables encapsulating
    local heaps and mutability within
    referentially-transparent code
  • These are the building blocks for implicitly
    parallel programs
  • Estimate 80 of CPU effort in Unreal can be
    parallelized this way

Space implications? Impact on performance?
32
Numeric Computation Example Collision Detection
  • A typical collision detection algorithm takes a
    line segment and determines when and where a
    point moving along that line will collide with a
    (constant) geometric dataset.

struct vec3 float x,y,z struct hit bool
DidCollide float Time vec3 Location hit
collide(vec3 start,vec3 end)
Vec3 data Vec3 float float float Hit data
Hit float Vec3 collide (vec3,vec3)-Maybe Hit
33
Numeric Computation Example Collision Detection
  • A typical collision detection algorithm takes a
    line segment and determines when and where a
    point moving along that line will collide with a
    (constant) geometric dataset.

struct vec3 float x,y,z struct hit bool
DidCollide float Time vec3 Location hit
collide(vec3 start,vec3 end)
Effects free
Vec3 data Vec3 float float float Hit data
Hit float Vec3 collide (vec3,vec3)-Maybe Hit
34
Language Implications
  • Effects Model
  • Purely Functional is the right default
  • Imperative constructs are vital features that
    must be exposed through explicit effects-typing
    constructs
  • Exceptions are an effect

In a concurrent world, imperative is the wrong
default
35
Concurrency in Numeric Computation
Referential transparency is promising
but what are the side effects?
36
Concurrency in Gameplay Simulation
  • This is the hardest problem
  • 10,000s of objects
  • Each one contains mutable state
  • Each one updated 30 times per second
  • Each update touches 5-10 other objects
  • Manual synchronization (shared state concurrency)
    is hopelessly intractable here.

37
Composable Memory Transactions
  • Composable memory transactions with concurrent
    Haskell
  • Modular, sequenced blocking with retry
  • Composable alternatives with orElse

How composable are these, really? Performance? Und
erlying support?
38
Concurrency in Gameplay SimulationSoftware
Transactional Memory
  • The idea
  • Update all objects concurrently in arbitrary
    order,with each update wrapped in an atomic
    ... block
  • With 10,000s of updates, and 5-10 objects
    touched per update, collisions will be low
  • 2-4X STM performance overhead is acceptableif
    it enables our state-intensive code to scale to
    many threads, its still a win

(Really?)
39
Concurrency in Gameplay Simulation
Manual, explicit synchronization is too hard
Claim Transactions are the only plausible
solution to concurrent mutable state
40
Three Kinds of Code
41
Parallelism and Purity
Physics, collision detection, scene traversal,
path finding, ..
Game World State
Software Transactional Memory
Graphics shader programs
Purely functional core
Data Parallel Subset
42
Parallelism and Purity
Physics, collision detection, scene traversal,
path finding, ..
Game World State
Software Transactional Memory
Graphics shader programs
Purely functional core
Data Parallel Subset
Can we learn anything from these?
Space? Performance?
Composability? Performance?
43
Reliability
44
Dynamic failure in mainstream languages
  • Example (C)Given a vertex array and an index
    array, we read and transform the indexed vertices
    into a new array.
  • What can possibly go wrong?

Vertex Transform (Vertex Vertices, int
Indices, Matrix m) Vertex Result new
VertexIndices.length for(int i0
iTransform(m,VerticesIndicesi) return
Result
45
Dynamic failure in mainstream languages
May contain indices outside of the range of the
Vertex array
May be NULL
May be NULL
May be NULL
Vertex Transform (Vertex Vertices, int
Indices, Matrix m) Vertex Result new
VertexIndices.length for(int i0
iTransform(m,VerticesIndicesi) return
Result
Array access might be out of bounds
Could dereference a NULL pointer
Will the compiler realize this cant fail?
  • Our code is littered with runtime failure cases,
  • Yet the compiler remains silent!
  • Dynamic failure is a big deal - awkward/error
    prone to prevent

46
Dynamic failure in mainstream languages
  • Solved problems
  • Random memory overwrites
  • Memory leaks (?)
  • Solvable
  • Accessing arrays out of bounds
  • Dereferencing null pointers
  • Integer overflow
  • Accessing uninitialized variables
  • 50 of the bugs in Unreal can be traced to these
    problems!

47
A better solution?
An index buffer containing natural numbers less
than n
Universally quantify over all natural numbers
An array of exactly known size
Transformnnat(VerticesnVertex,
Indicesnateach(i in Indices) Transform(m,Verticesi)
The only possible failure modedivergence, if
the call to Transform diverges.
Haskell-style array comprehension
48
How might this work?
  • Dependent types
  • Dependent functions
  • Universal quantification

The Integers
int nat nat
The Natural Numbers
The Natural Numbers less than n,where n may be a
variable!
Sum(nnat,xsnint)..aSum(3,7,8,9)
Explicit type/value dependency between function
parameters
Sumnnat(xsnint)..aSum(7,8,9)
Good ideas, though they make the compilers job
significantly harder
49
How might this work?
  • Separating the pointer to t conceptfrom the
    optional value of t concept
  • Advantages
  • You cant dereference a NULL pointer
  • The compiler can force you to do the appropriate
    error checks

A pointer to an integer
xpint xo?intxpo?int
An optional integer
An optional pointer to an integer!
?int x lookup(t, k) FOUND(x) - use x
NOTHING(x) - display error message of your
choice
50
How might this work?
  • Comprehensions (a la Haskell),for safely
    traversing and generating collections

Successors(xsint)int foreach(x in
xs) x1
Now we cant have an index out of bounds
error! But this ties the Collections object and
Iterator interface directly to the language -
sacrifice abstraction
51
How might this work?
  • A guarded casting mechanism for cases where need
    a safe escape
  • All potential failure must be explicitly handled,
    but we lose no expressiveness.

Here, we cast i totype of natural numbers
bounded by the length of as,and bind the result
to n
GetElement(asstring, iint)string
if(nnatOut of Bounds
We can only access iwithin this context
If the cast fails, we execute the else-branch
Now an exception cant happen
52
Concurrency and Reliability
  • There is a wonderful correspondence between
  • Features that aid reliability
  • Features that enable concurrency.
  • Example
  • Outlawing runtime exceptions through dependent
    types
  • Out of bounds array access
  • Null pointer dereference
  • Integer overflow
  • Exceptions impose sequencing constraints on
    concurrent execution.

Dependent types and concurrency must evolve
simultaneously
53
Analysis of Unreal code
  • Usage of integer variables in Unreal
  • 90 of integer variables in Unreal exist to index
    into arrays
  • 80 could be dependently-typed explicitly,guarant
    eeing safe array access without casting.
  • 10 would require casts upon array access.
  • The other 10 are used for
  • Computing summary statistics
  • Encoding bit flags
  • Various forms of low-level hackery
  • How true are these observations for other types
    of code?

54
Analysis of Unreal code
  • For loops in Unreal
  • 40 are functional comprehensions
  • 50 are functional folds
  • Functional comprehensions (foreach)
  • Functional folds
  • Operator to encapsulate simple patterns of
    recursion for processing lists

sum xs foldl () 0 xs sum (3, 4, 5) 12
We can exploit concurrency in addition to
preventing exceptions
55
Accessing uninitialized variables
  • Can we make this work?
  • This is a frequent bug. Data structures are often
    rearranged, changing the initialization order.
  • Lessons from Haskell
  • Lazy evaluation enables correct out-of-order
    evaluation
  • Accessing circularly entailed values causes thunk
    reentry (divergence), rather than just returning
    the wrong value
  • Lesson from Id90 Lenient evaluation is
    sufficient to guarantee this

class MyClass const int ac1 const int
b7 const int cb1MyClass myvalue new C
// What is myvalue.a?
56
What is lenient evaluation?
  • An evaluation strategy under which all reducible
    expressions are evaluated in parallel except
    inside the arms of conditionals and inside lambda
    abstractions.

57
Language implications
  • Evaluation Strategy
  • Lenient evaluation is the right default.
  • Support lazy evaluation through explicit
    suspend/evaluate constructs.
  • Eager evaluation is an optimization the compiler
    may perform when it is safe to do so.

58
Integer Overflow
  • The Natural Numbers
  • Factoid C exposes more than 10 integer-like
    data types, none of which are those defined by
    (Pythagoras, 500BC).
  • In the future, can we get integers right?

data Nat Zero Succ Nat
59
Can we get integers right?
  • Neat Trick
  • In a machine word (size 2n), encode an integer
    2n-1 or a pointer to a variable-precision
    integer
  • Thus small integers carry no storage cost
  • Additional access cost is 5 CPU instructions
  • But
  • Array indexes dont need this encoding
  • Since 80 of integers can dependently-typed to
    access into an array, the amortized cost is 1
    CPU instruction per integer operation.
  • How true is this for other application domains?

This could be a viable tradeoff
60
Dynamic failure Conclusion
  • Reasonable type-system extensions could
    statically eliminate all
  • Out-of-bounds array access (comprehensions,
    dependent types)
  • Null pointer dereference (optional variables)
  • Integer overflow (dependent types with pointer
    access)
  • Accessing of uninitialized variables (lenient
    evaluation)

61
Performance
62
Performance
  • Everything is performance sensitive
  • But
  • Productivity is just as important
  • Will sacrifice 10 performance for 10 higher
    productivity
  • No simple set of hotspots to optimize
  • To what extent does that trend scale?

63
Performance
  • Do you really give up performance in video games?
  • Poorer image quality
  • Physical simulation isnt quite as accurate
  • AI isnt as smart as it could be
  • Can we make that kind of tradeoff in other
    application domains?
  • Concurrency can be a performance win, but
  • Some of the techniques might be high overhead,
    compensating for some of the improvement

64
Language Implications
  • Memory model
  • Garbage collection should be the only option
  • Exception Model
  • The Java/C exceptions everywhere model should
    be wholly abandoned
  • All dereference and array accesses must be
    statically verifiable, rather than causing
    sequenced exceptions
  • No language construct except throw should
    generate an exception

65
A Brief History of Game Technology
1972 Pong (hardware) 1980 Zork (high level
interpreted language) 1993 DOOM (C) 1998
Unreal (C, Java-style scripting) 2005-6 Xbox
360, PlayStation 3with 6-8 hardware
threads 2009 Next console generation.
Unification of the CPU, GPU. Massive multi-core,
data parallelism, etc.
66
The Coming Crisis in Computing
  • By 2009, game developers will face
  • CPUs with
  • 20 cores
  • 80 hardware threads
  • 1 TFLOP of computing power
  • GPUs with general computing capabilities.
  • Game developers will be at the forefront.

67
Questions?
Write a Comment
User Comments (0)
About PowerShow.com