PARALLEL GRAPH SEARCH · SIMULATED GPU · 5 × 5 BOARD

Parallel BFS
Knight’s Tour Lab

Watch 25 logical GPU cores expand only feasible knight moves, discard dead ends, synchronize at each depth and discover every complete open tour on a 5×5 board.

25-bit visited maskall-to-all interconnectlevel-synchronous inboxesfeasible core-to-core messagesdead-end pruning(mask, endpoint) deduplicationclosed tour = impossible by parity
GPU: checking…
Why only open tours? A knight changes square colour on every move. A closed cycle must therefore contain an even number of squares, but 5×5 has 25. Closed tours are mathematically impossible; PBFS enumerates complete open tours.
Move depth0
Frontier25
Generated0
Dead ends0
Duplicates0
Explored0

Representative state

STATE 1 / 25Path: 1mask 0x0000001

25 board-resident GPU cores

VERTEX-CENTRIC · BULK SYNCHRONOUS
SOURCE CORE ↓ · DESTINATION CORE →0 routed messages

Level history

GLOBAL BARRIER AFTER EACH ROW
DepthFrontierExpandedGeneratedDead endsDuplicates
Ready at depth 0. Each board square is a core. Its initial state begins in the inbox of that core.

1. Frontier parallelism

A worker does not test all 16 board positions. It reads one state and enumerates only set bits in the precomputed legal-move mask. Core v owns board square v and its inbox contains every frontier state whose endpoint is v. It sends each legal child state directly to the destination-square core.

source = endpointCore
available = KNIGHT[source] & ~visited
while (available) {
  next = popLeastBit(available)
  emit(visited | bit(next), next)
}

2. Dead-end pruning

If a partial path has no feasible move before it visits all 16 squares, that branch cannot become a tour and is discarded immediately. This is exact pruning, not a heuristic guess.

if (depth < 24 && available == 0)
    discard(state)
else
    write(nextFrontier)

3. Global synchronization

PBFS completes every state at depth d before processing depth d+1. At depth 24 it enumerates every complete open tour. No closed-tour test is needed: an odd 25-vertex bipartite knight graph cannot contain a Hamiltonian cycle.

expand(frontier[d]) in parallel
prefix-sum child counts
barrier()
frontier[d + 1] = children