Asynchronous Advantage Actor-Critic (A3C)
Many CPU workers play their own copies of the game at once and push gradients to one shared brain without locks. The mixed updates decorrelate the data, so no replay buffer is needed.
Why Does This Exist?
Deep Q methods broke correlation with a million step replay store. That works for off policy Q learning, but on policy methods cannot reuse old data without correction. Actor critic methods need fresh rollouts from the current policy, so the buffer does not fit.
A3C replaces memory with parallelism. Each of workers holds its own environment copy and its own local weights for the policy and for the value baseline. Workers roll out up to steps, compute -step advantages, and push gradients to the shared model with no locks. Because the workers sit in different states at different times, the push stream is mixed enough to train stably on CPU.
This page covers the async push and the -step update. The sync follow up lives in advantage actor critic, the shared architecture in actor critic architecture, and continuous control notes in continuous action spaces.
You need policy gradients first: times advantage moves probability toward better actions.
Think of It Like This
Scouts phoning edits to one shared playbook
One playbook sits at HQ. Four scouts watch four different opponents with yesterday's copy. Each scout tests a short drill, phones in a small edit the moment it finishes, then pulls the latest playbook before the next drill.
No scout waits for the others, and HQ never locks the book. Because the calls come from different games, the edit stream stays balanced instead of overfitting to one opponent.
Where it stops: scouts write notes one at a time while A3C threads overwrite shared floats with Hogwild races. Stale edits are also real here: a slow scout phones in advice for a playbook that already moved on.
How It Actually Works
Each worker repeats pull, rollout, bootstrap, push. Local gradients start at zero, sync and , then step the private env for up to steps.
Bootstrapping sets at a terminal state else . Walking backward with discount :
Here is the one step reward, is the critic value, and is the advantage telling how much better this path ran than expected. Policy and value gradients accumulate with entropy bonus weighted by :
Then the Hogwild push writes straight to shared memory with step , no mutex:
The price is staleness: lags by the time the rollout took.
Worked example
Track shared weights in with . Both workers pull:
Worker 1 finishes fast with and pushes:
Worker 2 ran longer on the old copy and returns stale . It still pushes:
Both edits land. The second used a one update old view, which is the staleness A3C accepts.
Code
Deterministic replay of the two pushes above.
import numpy as np
def push(params: np.ndarray, grad: np.ndarray, lr: float = 0.10) -> np.ndarray: """One Hogwild style descent step, no locks in this model.""" return params - lr * grad
w = np.array([1.00, 2.00])g1 = np.array([0.40, -0.60])w = push(w, g1)print(np.round(w, 4)) # -> [0.96 2.06]
g2 = np.array([-0.50, 0.30])w = push(w, g2)print(np.round(w, 4)) # -> [1.01 2.03]Outputs match the hand steps: then .
Watch Out For
Too many workers make gradients too stale
A3C assumes delays stay short. With 32 threads or uneven episode lengths, a slow worker returns advice for a model that moved dozens of updates ago.
Symptom: sudden score collapse after adding cores, worse with longer episodes. Fix: cap workers near core count, use shared RMSprop statistics to damp odd pushes, or switch to advantage actor critic sync batches on GPU.
The Quick Version
- A3C decorrelates with parallel env copies, not with a replay store, so it stays on policy.
- Workers use -step bootstrapped advantages with plus an entropy bonus.
- Hogwild pushes skip locks for CPU speed and accept mild staleness.
- The traced run moves shared weights to to .
- Cap worker count or go sync A2C when staleness starts to hurt.