Workspace IndexAlgorithms › Day 11

Topological Sort and DAG Scheduling TODO

Algorithms · Day 11 / 100 · A. Advanced Algorithms & Data Structures (Day 1-19)

Concept

Topological sort orders the vertices of a directed acyclic graph (DAG) so that, for every edge u→v, u comes before v. Kahn's algorithm computes this in O(V+E) by queuing up vertices with in-degree 0 and, each time one is dequeued, decrementing the in-degree of its neighbors; if the queue empties while vertices remain, a cycle exists. From a scheduling angle, each step of the topological sort — the set of vertices whose in-degree hits 0 at the same time — can be grouped into one parallel layer, and the number of layers equals the length of the DAG's longest path. So even with infinite processors, the lower bound on execution time is the longest path, i.e. the critical path — this is the fundamental limit on parallel scheduling. In parallel transaction execution, the DAG's edges are defined by state-access conflicts (write-write or read-write on the same slot), and if the access lists are declared up front, this graph can be built statically before execution even starts.

Every design that tries to run transactions within a block in parallel eventually runs into the limit set by the conflict graph's longest path, so this calculation is what lets you estimate the maximum gain parallelization can actually deliver ahead of time.

Code & Formula

# Day 11: 위상정렬·DAG 스케줄링 — Kahn 알고리즘으로 순서·병렬 레이어·최장 경로를 구한다
# 진입차수 0인 정점을 레이어 단위로 소진시키면 위상순서와 병렬 실행 스케줄이 동시에 나온다.

from collections import defaultdict

def topo_layers(nodes, edges):
    graph = defaultdict(list)
    indeg = {n: 0 for n in nodes}
    for u, v in edges:
        graph[u].append(v)
        indeg[v] += 1

    layer = [n for n in nodes if indeg[n] == 0]
    layers, order, remaining = [], [], dict(indeg)
    while layer:
        layers.append(sorted(layer))
        order.extend(layer)
        next_layer = []
        for u in layer:
            for v in graph[u]:
                remaining[v] -= 1
                if remaining[v] == 0:
                    next_layer.append(v)
        layer = next_layer
    if len(order) != len(nodes):
        raise ValueError("사이클이 존재해 위상정렬 불가")
    return order, layers

# 트랜잭션 5개(A~E)가 스토리지 슬롯 접근으로 서로 의존(충돌)하는 상황을 DAG로 모델링
nodes = ["A", "B", "C", "D", "E"]
edges = [("A", "C"), ("B", "C"), ("C", "D"), ("C", "E")]   # A,B 끝나야 C 실행, C 끝나야 D,E 실행

order, layers = topo_layers(nodes, edges)
print("위상정렬 순서 =", order)
print("병렬 실행 레이어 =", layers)
print(f"레이어 수(=최장 경로 길이) = {len(layers)} -> {len(nodes)}개 트랜잭션을 {len(layers)}단계에 실행 가능")

Exercise

Write a program that takes an arbitrary list of transactions along with the storage keys each one reads and writes, builds the conflict DAG, and uses Kahn's algorithm to output the list of parallel layers and the longest-path length.

Practical Connection

When Verex's CLOB matching results get settled as multiple transactions, ones that only touch different markets or different position tokens are independent in the conflict graph — meaning they can be grouped into a parallel layer, with room to lower batch-processing cost.

Where it lands in Jayverse

Key expressions

Words and phrases from this page worth keeping, with the Korean meaning and the sentence they come from.

Expression뜻 · 쓰이는 자리
critical path임계 경로(전체 소요시간을 결정짓는 최장 경로) · 병렬 처리의 이론적 한계를 논할 때 · "i.e. the critical path — this is the fundamental limit"
lower bound하한선 · 아무리 자원이 많아도 넘을 수 없는 한계치 · "the lower bound on execution time is the longest path"
runs into(한계·문제에) 부딪히다 · 병렬 실행 설계가 결국 한계에 도달할 때 · "eventually runs into the limit set by"
up front사전에·미리 · 접근 목록을 실행 전에 미리 선언할 때 · "if the access lists are declared up front"
in-degree진입 차수(그래프 정점으로 들어오는 간선 수) · 위상 정렬 알고리즘의 핵심 개념 · "queuing up vertices with in-degree 0"
conflict graph충돌 그래프(트랜잭션 간 상태 접근 충돌을 표현) · 병렬 실행 가능 여부를 판단하는 자료구조 · "the conflict graph's longest path"
ahead of time미리·사전에 · 병렬화로 얻을 최대 이득을 미리 추정할 때 · "can actually deliver ahead of time"
room to lower낮출 여지·개선 여지 · 배치 처리 비용을 줄일 가능성을 말할 때 · "with room to lower batch-processing cost"
DAG방향성 비순환 그래프(Directed Acyclic Graph) · 사이클이 없는 방향 그래프, 위상 정렬의 대상이 되는 구조 · "orders the vertices of a directed acyclic graph (DAG)"
CLOB중앙집중형 지정가 주문장(Central Limit Order Book) · 거래소 주문 매칭 결과를 가리킬 때 · "When Verex's CLOB matching results get settled"

If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.


한국어

위상정렬·DAG 스케줄링 TODO

Algorithms · Day 11 / 100 · A. 고급 알고리즘·자료구조 (Day 1–19)

개념

위상정렬은 방향 비순환 그래프(DAG)의 정점을 모든 간선 u→v에 대해 u가 v보다 앞서도록 나열하는 것이다. Kahn 알고리즘은 진입차수 0인 정점을 큐에 넣고 꺼낼 때마다 인접 정점의 진입차수를 줄이는 방식으로 O(V+E)에 이를 계산하며, 큐가 비었는데 남은 정점이 있으면 사이클이 존재한다는 뜻이다. 스케줄링 관점에서는 위상정렬의 각 단계, 즉 동시에 진입차수가 0이 되는 정점 집합을 하나의 병렬 레이어로 묶을 수 있고, 이때 레이어 수는 DAG의 최장 경로 길이와 같다. 따라서 프로세서가 무한히 많아도 실행 시간의 하한은 최장 경로(critical path)이며, 이것이 병렬 스케줄의 근본 한계다. 트랜잭션 병렬 실행에서 DAG의 간선은 상태 접근 충돌(같은 슬롯에 대한 write-write 또는 read-write)로 정의되고, 접근 목록이 사전에 선언되면 이 그래프를 실행 전에 정적으로 구성할 수 있다.

블록 내 트랜잭션을 병렬로 돌리려는 모든 설계는 결국 '충돌 그래프의 최장 경로'라는 한계에 부딪히므로, 병렬화로 얻을 수 있는 최대 이득을 미리 추정하려면 이 계산이 필요하다.

코드 · 수식

# Day 11: 위상정렬·DAG 스케줄링 — Kahn 알고리즘으로 순서·병렬 레이어·최장 경로를 구한다
# 진입차수 0인 정점을 레이어 단위로 소진시키면 위상순서와 병렬 실행 스케줄이 동시에 나온다.

from collections import defaultdict

def topo_layers(nodes, edges):
    graph = defaultdict(list)
    indeg = {n: 0 for n in nodes}
    for u, v in edges:
        graph[u].append(v)
        indeg[v] += 1

    layer = [n for n in nodes if indeg[n] == 0]
    layers, order, remaining = [], [], dict(indeg)
    while layer:
        layers.append(sorted(layer))
        order.extend(layer)
        next_layer = []
        for u in layer:
            for v in graph[u]:
                remaining[v] -= 1
                if remaining[v] == 0:
                    next_layer.append(v)
        layer = next_layer
    if len(order) != len(nodes):
        raise ValueError("사이클이 존재해 위상정렬 불가")
    return order, layers

# 트랜잭션 5개(A~E)가 스토리지 슬롯 접근으로 서로 의존(충돌)하는 상황을 DAG로 모델링
nodes = ["A", "B", "C", "D", "E"]
edges = [("A", "C"), ("B", "C"), ("C", "D"), ("C", "E")]   # A,B 끝나야 C 실행, C 끝나야 D,E 실행

order, layers = topo_layers(nodes, edges)
print("위상정렬 순서 =", order)
print("병렬 실행 레이어 =", layers)
print(f"레이어 수(=최장 경로 길이) = {len(layers)} -> {len(nodes)}개 트랜잭션을 {len(layers)}단계에 실행 가능")

연습

임의의 트랜잭션 목록과 각 트랜잭션이 읽고 쓰는 스토리지 키 집합을 입력으로 받아 충돌 DAG를 만들고, Kahn 알고리즘으로 병렬 레이어 목록과 최장 경로 길이를 출력하는 프로그램을 작성해 보라.

실무 · Verex 연결

Verex의 CLOB 매칭 결과를 여러 트랜잭션으로 정산할 때, 서로 다른 마켓·서로 다른 포지션 토큰만 건드리는 트랜잭션들은 충돌 그래프에서 독립적이므로 병렬 레이어로 묶여 배치 처리 비용을 낮출 여지가 있다.

Jayverse에서의 위치

핵심 표현

이 페이지의 영어 본문에서 배울 만한 단어와 표현, 뜻과 나온 자리.

Expression뜻 · 쓰이는 자리
critical path임계 경로(전체 소요시간을 결정짓는 최장 경로) · 병렬 처리의 이론적 한계를 논할 때 · "i.e. the critical path — this is the fundamental limit"
lower bound하한선 · 아무리 자원이 많아도 넘을 수 없는 한계치 · "the lower bound on execution time is the longest path"
runs into(한계·문제에) 부딪히다 · 병렬 실행 설계가 결국 한계에 도달할 때 · "eventually runs into the limit set by"
up front사전에·미리 · 접근 목록을 실행 전에 미리 선언할 때 · "if the access lists are declared up front"
in-degree진입 차수(그래프 정점으로 들어오는 간선 수) · 위상 정렬 알고리즘의 핵심 개념 · "queuing up vertices with in-degree 0"
conflict graph충돌 그래프(트랜잭션 간 상태 접근 충돌을 표현) · 병렬 실행 가능 여부를 판단하는 자료구조 · "the conflict graph's longest path"
ahead of time미리·사전에 · 병렬화로 얻을 최대 이득을 미리 추정할 때 · "can actually deliver ahead of time"
room to lower낮출 여지·개선 여지 · 배치 처리 비용을 줄일 가능성을 말할 때 · "with room to lower batch-processing cost"
DAG방향성 비순환 그래프(Directed Acyclic Graph) · 사이클이 없는 방향 그래프, 위상 정렬의 대상이 되는 구조 · "orders the vertices of a directed acyclic graph (DAG)"
CLOB중앙집중형 지정가 주문장(Central Limit Order Book) · 거래소 주문 매칭 결과를 가리킬 때 · "When Verex's CLOB matching results get settled"

공부한 날 원본 커리큘럼(docs/knowledge/dev-100-curriculum.md)의 이 줄에 노트 링크와 ✅ 를 붙이면, 이 자리는 노트 본문으로 바로 이어집니다. 노트 없이 이 페이지에 바로 적어도 됩니다 — 다만 다시 생성하면 덮어쓰이므로, 남길 글은 docs/algorithms/ 의 마크다운으로 쓰는 편이 안전합니다.

← 1063. 세그먼트 트리 심화1065. 최대 유량·최소 컷과 매칭 →