Skip to main content
added 12 characters in body
Source Link
John McDonald
  • 6.8k
  • 2
  • 33
  • 46

Assuming your Update() methods look like this:

for each entity in allEntities
{
    entity.Update()
}

You'd need to either synchronize (aka lock) the entire loop:

lock(allEntities)
{
    for each entity in allEntities
    {
        entity.Update()
    }
}

Preventing almost any multi-threading gain. The other way would be to synchronize around each and every entity update call:

for each entity in allEntities
{
    lock(entity)
    {
        entity.Update()
    }
}

Again, preventing almost any multi-threading gain and is probably much slower than just synchronizing the whole loop. Synchronizations are expensive:

Another reason to avoid having many locks in a system is the cost of entering and leaving a lock. The lightest locks use a special compare/exchange instruction to check whether the lock is taken, and if it isn't, they enter the lock in a single atomic action. Unfortunately, this special instruction is relatively expensive (typically ten to hundreds of times longer than an ordinary instruction)

http://msdn.microsoft.com/en-ca/magazine/cc163744.aspx

That said, there are multi-threaded solutions that either avoid or minimize locking. One way is to use 1 thread for the core game and other threads for non-core game elements, like generating and animating trees and animals in Flight Sim X [ref].

An other way to do it is to have 2 copies of every game entity (wasteful, I know). One copy would be the present copy, and the other would be the past copy. The present copy is strictly write only, and the past copy is strictly read only. When you go to update, you assign ranges of your entity list to as many threads as you see fit. Each thread has write-access to the present copies in the assigned range and every thread has read-access to the all past copies of the entities, and thus can update the assigned present copies using data from the past copies with no locking. Between each frame, the present copy becomes the past copy, however you want to handle the swapping of roles. [citation needed]

I hope I've givenIf you a little insight into how multiaren't noticing performance issues, I wouldn't change anything. Multi-threading issues can (and can't) be used efficiently in gamestough to track down.

Assuming your Update() methods look like this:

for each entity in allEntities
{
    entity.Update()
}

You'd need to either synchronize (aka lock) the entire loop:

lock(allEntities)
{
    for each entity in allEntities
    {
        entity.Update()
    }
}

Preventing almost any multi-threading gain. The other way would be to synchronize around each and every entity update call:

for each entity in allEntities
{
    lock(entity)
    {
        entity.Update()
    }
}

Again, preventing almost any multi-threading gain. Synchronizations are expensive:

Another reason to avoid having many locks in a system is the cost of entering and leaving a lock. The lightest locks use a special compare/exchange instruction to check whether the lock is taken, and if it isn't, they enter the lock in a single atomic action. Unfortunately, this special instruction is relatively expensive (typically ten to hundreds of times longer than an ordinary instruction)

http://msdn.microsoft.com/en-ca/magazine/cc163744.aspx

That said, there are multi-threaded solutions that either avoid or minimize locking. One way is to use 1 thread for the core game and other threads for non-core game elements, like generating and animating trees and animals in Flight Sim X [ref].

An other way to do it is to have 2 copies of every game entity (wasteful, I know). One copy would be the present copy, and the other would be the past copy. The present copy is strictly write only, and the past copy is strictly read only. When you go to update, you assign ranges of your entity list to as many threads as you see fit. Each thread has write-access to the present copies in the assigned range and every thread has read-access to the all past copies of the entities, and thus can update the assigned present copies using data from the past copies with no locking. Between each frame, the present copy becomes the past copy, however you want to handle the swapping of roles. [citation needed]

I hope I've given you a little insight into how multi-threading can (and can't) be used efficiently in games.

Assuming your Update() methods look like this:

for each entity in allEntities
{
    entity.Update()
}

You'd need to either synchronize (aka lock) the entire loop:

lock(allEntities)
{
    for each entity in allEntities
    {
        entity.Update()
    }
}

Preventing almost any multi-threading gain. The other way would be to synchronize around each and every entity update call:

for each entity in allEntities
{
    lock(entity)
    {
        entity.Update()
    }
}

Again, preventing almost any multi-threading gain and is probably much slower than just synchronizing the whole loop. Synchronizations are expensive:

Another reason to avoid having many locks in a system is the cost of entering and leaving a lock. The lightest locks use a special compare/exchange instruction to check whether the lock is taken, and if it isn't, they enter the lock in a single atomic action. Unfortunately, this special instruction is relatively expensive (typically ten to hundreds of times longer than an ordinary instruction)

http://msdn.microsoft.com/en-ca/magazine/cc163744.aspx

That said, there are multi-threaded solutions that either avoid or minimize locking. One way is to use 1 thread for the core game and other threads for non-core game elements, like generating and animating trees and animals in Flight Sim X [ref].

An other way to do it is to have 2 copies of every game entity (wasteful, I know). One copy would be the present copy, and the other would be the past copy. The present copy is strictly write only, and the past copy is strictly read only. When you go to update, you assign ranges of your entity list to as many threads as you see fit. Each thread has write-access to the present copies in the assigned range and every thread has read-access to the all past copies of the entities, and thus can update the assigned present copies using data from the past copies with no locking. Between each frame, the present copy becomes the past copy, however you want to handle the swapping of roles. [citation needed]

If you aren't noticing performance issues, I wouldn't change anything. Multi-threading issues can be tough to track down.

Source Link
John McDonald
  • 6.8k
  • 2
  • 33
  • 46

Assuming your Update() methods look like this:

for each entity in allEntities
{
    entity.Update()
}

You'd need to either synchronize (aka lock) the entire loop:

lock(allEntities)
{
    for each entity in allEntities
    {
        entity.Update()
    }
}

Preventing almost any multi-threading gain. The other way would be to synchronize around each and every entity update call:

for each entity in allEntities
{
    lock(entity)
    {
        entity.Update()
    }
}

Again, preventing almost any multi-threading gain. Synchronizations are expensive:

Another reason to avoid having many locks in a system is the cost of entering and leaving a lock. The lightest locks use a special compare/exchange instruction to check whether the lock is taken, and if it isn't, they enter the lock in a single atomic action. Unfortunately, this special instruction is relatively expensive (typically ten to hundreds of times longer than an ordinary instruction)

http://msdn.microsoft.com/en-ca/magazine/cc163744.aspx

That said, there are multi-threaded solutions that either avoid or minimize locking. One way is to use 1 thread for the core game and other threads for non-core game elements, like generating and animating trees and animals in Flight Sim X [ref].

An other way to do it is to have 2 copies of every game entity (wasteful, I know). One copy would be the present copy, and the other would be the past copy. The present copy is strictly write only, and the past copy is strictly read only. When you go to update, you assign ranges of your entity list to as many threads as you see fit. Each thread has write-access to the present copies in the assigned range and every thread has read-access to the all past copies of the entities, and thus can update the assigned present copies using data from the past copies with no locking. Between each frame, the present copy becomes the past copy, however you want to handle the swapping of roles. [citation needed]

I hope I've given you a little insight into how multi-threading can (and can't) be used efficiently in games.