{ "version": "1.1", "id": "numa-vcpu-and-memory-placement", "title": "vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다", "question": "vCPU pinning 만 한 배치와 memory binding 까지 맞춘 배치에서 같은 memory 접근은 각각 어느 node 의 RAM 에 닿는가", "type": "sequence", "direction": "LR", "audience": [ "가상 머신의 지연을 NUMA 배치로 의심하는 사람", "vCPU pinning 을 걸어 두고 효과가 없다고 느끼는 사람" ], "summary": "vCPU thread 를 Node 0 CPU 에 pinning 해도 VM1 의 memory backing 이 Node 1 에 놓여 있으면 접근은 remote 로 남고, memory placement 와 binding 까지 Node 0 으로 맞춘 뒤에야 같은 접근이 local 이 된다.", "alt": "QEMU vCPU Thread, VM1 Memory Backing, Node 0 CPU, Node 0 RAM, Node 1 RAM 다섯 참여자 사이의 순서도. 앞 세 메시지는 pinning 만 한 배치에서 접근이 Node 1 RAM 으로 가는 것을, 뒤 두 메시지는 memory 를 Node 0 에 묶은 배치에서 같은 접근이 Node 0 RAM 으로 가는 것을 보인다.", "long_description": "참여자는 왼쪽부터 QEMU vCPU Thread, VM1 Memory Backing, Node 0 CPU, Node 0 RAM, Node 1 RAM 다섯이다. 메시지는 위에서 아래로 읽는다. 1번에서 vCPU thread 가 Node 0 CPU 에 pinning 되고, 2번에서 VM1 의 memory backing 이 Node 1 에 놓인다. 그 배치에서 3번의 memory 접근은 Node 1 RAM 으로 가고 이것이 remote access 다. Node 0 과 Node 1 사이에는 interconnect 가 있어 이 접근만 그 구간을 건넌다. 4번과 5번은 그 뒤에 일어나는 다른 사건이 아니라 배치를 고친 구성이다. memory placement 와 binding 까지 Node 0 으로 맞추면 같은 접근이 Node 0 RAM 으로 가고 local access 가 된다. 접근 비용이 실제로 얼마나 차이 나는지, 이 Host 가 몇 개의 node 를 가졌는지는 그림이 말하지 않는다.", "source_context": { "document": "docs/virtualization/final/document.md", "document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd", "anchor": { "kind": "heading", "value": "75. vCPU와 NUMA의 연결", "line": 3313 } }, "composition": { "profile": "sequence", "diagram_only": true, "reference_ids": [ "payment-approval-sequence" ], "rationale": "이 절과 다음 절이 세운 것은 배치 하나가 아니라 「묶은 것 → 남은 문제 → 마저 묶은 것 → 달라진 결과」라는 차례다. orchestrator-workers 는 scheduler 를 워커들 위에 두는 그림인데 memory 가 어느 node 에 있는지는 scheduler 가 정하지 않는다는 것이 이 절의 논지라 그 문법을 쓰면 논지가 뒤집힌다. query-fanout 은 CPU 하나가 RAM 둘로 갈라지는 모양은 맞지만 pinning 만 한 배치와 memory 까지 맞춘 배치가 같은 그림에서 구별되지 않는다. sequence 는 메시지에 번호를 붙이므로 두 배치가 어느 쪽이 먼저이고 무엇이 달라졌는지 그대로 드러난다.", "focus_node": "node0-cpu" }, "groups": [], "nodes": [ { "id": "qemu-vcpu-thread", "label": "QEMU vCPU Thread", "kind": "process", "role": "participant", "shape": "box", "emphasis": "primary", "details": [ "Guest vCPU" ], "description": "Guest vCPU 가 Host 에서 갖는 실체. Host scheduler 가 이것을 logical CPU 에 올린다.", "evidence": [ { "start_line": 3315, "end_line": 3324 } ], "assumption": false }, { "id": "vm-memory-backing", "label": "VM1 Memory Backing", "kind": "memory", "role": "participant", "shape": "box", "details": [ "VM1 RAM" ], "description": "그 가상 머신의 Host physical backing page 가 놓이는 자리.", "evidence": [ { "start_line": 3327, "end_line": 3327 }, { "start_line": 3352, "end_line": 3354 }, { "start_line": 3381, "end_line": 3382 } ], "assumption": false }, { "id": "node0-cpu", "label": "Node 0 CPU", "kind": "compute", "role": "participant", "shape": "box", "emphasis": "primary", "details": [ "Host Logical CPU" ], "description": "vCPU thread 가 실행되는 logical CPU. NUMA Node 0 에 속한다.", "evidence": [ { "start_line": 3322, "end_line": 3330 } ], "assumption": false }, { "id": "node0-ram", "label": "Node 0 RAM", "kind": "memory", "role": "participant", "shape": "box", "details": [ "Local Memory" ], "description": "Node 0 CPU 와 같은 node 의 RAM.", "evidence": [ { "start_line": 3288, "end_line": 3296 }, { "start_line": 3373, "end_line": 3382 } ], "assumption": false }, { "id": "node1-ram", "label": "Node 1 RAM", "kind": "memory", "role": "participant", "shape": "box", "details": [ "Remote Memory" ], "description": "다른 node 의 RAM. Node 0 CPU 가 읽으면 interconnect 를 건넌다.", "evidence": [ { "start_line": 3299, "end_line": 3306 }, { "start_line": 3334, "end_line": 3334 } ], "assumption": false } ], "edges": [ { "id": "vcpu-pinning", "from": "qemu-vcpu-thread", "to": "node0-cpu", "label": "vCPU Pinning", "kind": "control", "order": 1, "style": "solid", "evidence": [ { "start_line": 3322, "end_line": 3324 }, { "start_line": 3347, "end_line": 3350 } ], "assumption": false }, { "id": "backing-on-node1", "from": "vm-memory-backing", "to": "node1-ram", "label": "Memory Placement", "kind": "control", "order": 2, "style": "solid", "evidence": [ { "start_line": 3327, "end_line": 3327 }, { "start_line": 3352, "end_line": 3354 } ], "assumption": false }, { "id": "remote-access", "from": "node0-cpu", "to": "node1-ram", "label": "Remote Access", "kind": "read", "order": 3, "style": "dashed", "evidence": [ { "start_line": 3329, "end_line": 3339 }, { "start_line": 3356, "end_line": 3357 } ], "assumption": false }, { "id": "memory-binding", "from": "vm-memory-backing", "to": "node0-ram", "label": "Memory Binding", "kind": "control", "order": 4, "style": "solid", "evidence": [ { "start_line": 3361, "end_line": 3366 }, { "start_line": 3381, "end_line": 3382 } ], "assumption": false }, { "id": "local-access", "from": "node0-cpu", "to": "node0-ram", "label": "Local Access", "kind": "read", "order": 5, "style": "solid", "evidence": [ { "start_line": 3288, "end_line": 3296 }, { "start_line": 3373, "end_line": 3382 } ], "assumption": false } ], "legend": [], "metadata": { "rationale": "sequence 로 고른 이유는 §76 이 배치 하나를 서술한 절이 아니라 「pinning 만 하면 이렇게 되고 memory 까지 맞추면 저렇게 된다」는 차례로 쓰인 절이기 때문이다. 4·5 번은 3 번 뒤에 일어나는 사건이 아니라 고친 구성이고 그 사실은 long_description 과 옆 문단이 말한다. remote access 에 emphasis: warning 을 줬더니 렌더러가 화살표 끝에 빨간 X 를 그려 실패로 읽혔다. remote 는 실패가 아니라 비용이 더 드는 접근이라 강조를 빼고 점선만 남겼다. interconnect 는 그림 안 이름으로 넣지 않고 와 노드 설명에 두었다 — 이름이 아니라 두 node 사이의 구간이라 상자도 화살표도 아니다. 접근 비용의 크기와 이 Host 의 node 수는 이 SSOT 가 재지 않았으므로 그리지 않았다." } }