You

pull은 propagation을 하는 중에 optimizer 들을 gpu에다가 던진다는거지? 아닌가? pull push를 조금만 더 설명해줘. optimizer 관련된 얘기같은데

Assistant

네, 그렇게 이해하면 약간 틀립니다.
Hydraulis에서 pull/push는 “optimizer를 GPU에 던진다”는 뜻이 아니라,
optimization phase와 propagation phase 사이에서 파라미터/그래디언트를 주고받는 동작을 말합니다.

아주 짧게 정리하면:

  • pull:
    propagation 쪽이 forward/backward를 하려면 필요한 parameter shard들을 가져오는 것
  • push:
    backward가 끝난 뒤 나온 gradient를 optimization 쪽으로 되돌려 보내는 것

즉, optimizer 자체를 전송하는 게 아니라,
optimizer가 다루는 모델 상태(model states) 와 gradient 를 주고받는 구조예요.

핵심 그림

Hydraulis는 역할을 둘로 나눕니다.

1) optimization phase

여기서는 주로:

  • FP32 parameters
  • optimizer states
    예: Adam의 momentum, variance 같은 것

을 sharded / fully sharded 형태로 유지합니다.

즉, optimizer 상태는 이쪽에 “고정”되어 있다고 보면 됩니다.
propagation이 도는 동안 매번 optimizer state를 여기저기 옮기는 게 아니라,
이 상태를 기준점처럼 둡니다.

2) propagation phase

여기서는:

  • forward
  • backward

를 실제로 실행합니다.
이때 필요한 parameter가 있으면 pull 해서 가져오고,
gradient가 생기면 push 해서 optimization 쪽으로 돌려줍니다.


pull이 정확히 뭐냐

pull은 말 그대로:

“지금 propagation을 하려면 이 레이어의 parameter가 필요하니까,
optimization 쪽에 있는 shard를 가져와서 현재 pipeline의 partition에 맞게 재구성(reshard)하자”

입니다.

예를 들어:

  • optimization 쪽에서는 parameter가 어떤 방식으로 shard되어 있고
  • propagation 쪽에서는 pipeline마다 TP/PP/CP 구성이 다를 수 있잖아요.

그러면 propagation이 필요한 순간에
그 pipeline이 쓰는 병렬 전략에 맞게 parameter를 받아와야 합니다.
이때 쓰는 게 pull이에요.

중요한 점:

  • pull은 optimizer state를 계산하기 위한 것이 아니라
  • forward/backward를 수행할 parameter를 준비하는 것

입니다.


push가 정확히 뭐냐

push는 backward 끝난 뒤에:

“이 pipeline에서 계산한 gradient를 다시 optimization 쪽의 shard 구조에 맞게 돌려보내자”

입니다.

왜 필요하냐면, propagation은 pipeline마다 병렬 구성이 다를 수 있는데, optimizer update는 결국 일관된 parameter/optimizer-state layout 위에서 해야 하거든요.

그래서 gradient를 그냥 로컬에만 두는 게 아니라
optimization phase의 저장 구조에 맞게 합치고(sync/reshard) 넘깁니다.


optimizer와의 관계

사용자님이 느낀 “optimizer 관련된 얘기 같아”는 맞습니다.
다만 정확히는:

  • optimizer는 pull/push의 대상이 아님
  • pull/push는 optimizer가 관리하는 parameter/gradient 흐름을 지원하는 통신 메커니즘

입니다.

좀 더 직관적으로 말하면:

  • optimizer state: “업데이트를 담당하는 본체”
  • pull: “학습할 때 필요한 파라미터를 꺼내오는 과정”
  • push: “학습 끝난 gradient를 다시 반납하는 과정”

이라고 보면 됩니다.


왜 이런 분리가 필요하냐

기존 방식에서는 보통 모든 pipeline이 같은 병렬 전략을 써서, parameter shard 구조와 gradient sync 구조가 단순했어요.

그런데 Hydraulis는 pipeline마다 병렬 전략이 달라질 수 있으니까:

  • 어떤 pipeline은 TP가 크고
  • 어떤 pipeline은 PP가 크고
  • 어떤 pipeline은 CP 구성이 다를 수 있음

이때는 parameter/gradient를 전략별로 다시 맞춰주는 작업이 필요합니다.
그걸 일반화한 것이 pull/push + LNK예요.


아주 짧은 예시

가령:

  • optimization 쪽에 parameter가 shard A/B/C로 저장되어 있고
  • pipeline 1은 <TP=2, PP=4>
  • pipeline 2는 <TP=4, PP=2>

라고 해봅시다.

그러면:

  1. pipeline 1이 forward를 하려면 필요한 shard를 pull
  2. backward 후 gradient를 계산하면 그것을 optimization 쪽 shard 구조에 맞게 push
  3. pipeline 2도 자기 전략에 맞는 방식으로 다시 pull/push

이렇게 됩니다.


한 줄로 다시 말하면

  • pull = optimizer 상태를 가져오는 게 아니라, forward/backward에 필요한 parameter를 가져오는 것
  • push = optimizer를 보내는 게 아니라, gradient를 optimizer가 쓸 수 있는 형태로 돌려보내는 것

원하시면 다음 답변에서 제가
“optimization phase / propagation phase / pull / push / LNK”를 하나의 그림처럼 순서도로 설명해드릴게요.

You

그러면 너무 느린거아니야? 언제마다 pull push하는데? 예를들어서 minibatch가 있다고 쳐 그러면 minibatch를 어떻게 나누고 planning을 어떻게하고 weight shard 들을 어떻게 바꾸는지 논리 정연한 설명이 필요해

Assistant

맞아요. 이 설계는 너무 자주 pull/push 하면 느려질 수밖에 있습니다.
그래서 Hydraulis는 “매 토큰마다”나 “레이어마다 계속 바꾸는” 식이 아니라, iteration 단위 + pipeline 단위로 계획을 세워서 묶어서 처리하려고 합니다.

아래처럼 보면 가장 이해가 쉽습니다.


1) 큰 단위부터: iteration 하나를 어떻게 보나

Hydraulis에서 보통 한 iteration은:

  1. 이번 iteration에 들어올 sequence들을 모음
  2. 길이 분포를 보고
  3. 어떤 pipeline 전략들을 쓸지 정함
  4. sequence들을 pipeline들에 배정(dispatch)
  5. 각 pipeline 안에서 micro-batch packing
  6. forward/backward 수행
  7. gradient를 optimization 쪽으로 push
  8. optimizer update

이 순서입니다.

즉, pull/push는 minibatch 안의 매 순간마다 일어나는 게 아니라,
미리 정한 packing/dispatch 결과를 실행할 때 필요한 시점에만 일어납니다.


2) minibatch를 어떻게 나누나

여기서 용어를 정리해야 해요.

  • global minibatch: 한 iteration에 처리할 전체 sequence 집합
  • micro-batch: pipeline parallel 때문에 더 잘게 나눈 실행 단위

Hydraulis는 global minibatch를 먼저 보고, 그 안의 sequence들을 어떤 pipeline이 맡을지(dispatch) 정한 뒤, 각 pipeline 내부에서는 micro-batch packing을 합니다.

즉 흐름은:

global minibatch → pipeline 간 dispatch → pipeline 내부 packing → micro-batch 실행

입니다.


3) planning은 언제 하냐

핵심은 실행 전에 계획한다는 겁니다.

Hydraulis는 데이터 길이 분포와 각 병렬 전략의 profiling cost를 이용해서:

  • 어떤 전략들이 유망한지 후보를 만들고
  • 이번 iteration에서는 그 후보 중 어떤 전략 조합이 좋은지 고르고
  • sequence들을 그 전략들에 맞게 배정합니다.

즉 planning은 대충 이런 순서예요:

A. 사전 준비

학습 전에 또는 주기적으로:

  • 각 strategy의 MaxLen(P)
  • 각 길이에서의 latency T(l, P)
  • 통신/연산 비용

을 profiling 해 둡니다.

B. iteration 시작 시

이번 iteration의 sequence length들을 보고:

  1. 가능한 strategy 후보를 고름
  2. 그 후보들에 sequence들을 분배할 계획을 계산
  3. 각 pipeline 내부 micro-batch packing 계산
  4. 실행

이 말은 곧, pull/push를 줄이기 위해 먼저 “어떤 shard 변환이 필요한지”를 계획해두고, 실행 중에는 그 계획대로만 움직인다는 뜻입니다.


4) weight shard는 어떻게 바뀌나

이게 핵심이에요.
Hydraulis는 optimizer phase의 shard layout과 propagation phase의 shard layout을 분리합니다.

optimization phase

여기는 비교적 고정입니다.

  • FP32 parameters
  • optimizer states

를 shard된 형태로 유지합니다.

이 상태를 기준 저장소처럼 생각하면 됩니다.

propagation phase

여기서는 pipeline마다 병렬 전략이 다를 수 있어서, 각 pipeline이 필요한 형태로 parameter를 가져와야 합니다.

여기서 LNK(link) 가 작동합니다.


5) pull/push가 실제로 무슨 일을 하냐

pull

pipeline이 어떤 레이어를 계산하려고 할 때:

  1. optimization 쪽에 저장된 parameter shard를 확인
  2. 현재 pipeline의 TP/PP/CP 구성에 맞게
  3. 필요한 parameter를 재분할/재배치해서
  4. propagation 쪽에서 쓸 수 있게 준비

즉 pull은 parameter를 “현재 실행용 layout”으로 가져오는 reshard 작업입니다.

중요:

  • 이건 매 토큰마다가 아니라
  • 해당 parameter가 필요한 시점에만
  • 그리고 미리 계획된 micro-batch 실행 흐름에 따라 일어납니다.

push

backward가 끝나면 gradient가 생기죠.

  1. propagation 쪽 layout에서 gradient가 계산됨
  2. optimization 쪽 shard layout에 맞게 합쳐짐
  3. optimizer update가 가능하도록 전달됨

즉 push는 gradient를 원래 optimizer layout으로 되돌려 놓는 과정입니다.


6) “너무 자주 바꾸면 느리지 않나?”에 대한 답

맞습니다. 그래서 Hydraulis는 매번 완전히 다시 셔플하는 방식이 아니라,
큰 덩어리로 계획하고, 그 계획 내에서는 통신을 겹쳐서 숨기려는 구조를 씁니다.

논리적으로는 이렇게 이해하면 돼요.

바보 같은 방식

  • sequence 하나마다 pull
  • 레이어 하나마다 push
  • 전략도 계속 바꿈

→ 너무 느림

Hydraulis 방식

  • iteration 시작 전에 계획
  • 같은 pipeline 안에서는 같은 전략을 묶어서 사용
  • 필요한 pull/push는 subgraph 단위로 캡슐화
  • computation과 overlap

→ 통신을 줄이고, 남는 통신도 계산 뒤에 숨김

즉, 느린 걸 인정하고,
느린 작업을 “자주” 하지 않도록 planning으로 묶는 것이 핵심입니다.


7) 예시로 끝까지 설명

예를 들어 한 iteration에 sequence 8개가 있다고 해봅시다.

길이:

  • 512
  • 1024
  • 128
  • 4096
  • 2048
  • 256
  • 8192
  • 1024

Hydraulis는 먼저 이걸 보고:

  1. 이 iteration에서 어떤 pipeline 전략들이 유리한지 판단
  2. 예를 들어 pipeline A는 짧은 sequence에 유리
  3. pipeline B는 긴 sequence에 유리
  4. sequence들을 A/B에 배정
  5. 각 pipeline 내부에서 micro-batch packing

을 합니다.

이제 실행:

  • pipeline A가 첫 micro-batch를 계산하기 전에 필요한 parameter를 pull
  • forward/backward 수행
  • backward 후 gradient를 push
  • pipeline B도 자기 차례에 같은 식으로 수행

즉, pull/push는 sequence별로 마음대로 막 일어나는 게 아니라,
배정된 pipeline이 자기 micro-batch를 실행할 때 필요한 parameter/gradient 경계에서 발생합니다.


8) 가장 중요한 직관

이 논문의 본질은:

“모델 상태를 계속 바꾸는 시스템”이 아니라
“모델 상태의 기준점은 유지하고, propagation을 위한 view만 필요할 때 재구성하는 시스템”

에 가깝습니다.

그래서 weight shard는 자주 “저장 위치 자체”가 바뀌는 게 아니라, 실행에 필요한 관점에서 재배치되는 것에 가깝습니다.


9) 한 문장 요약

  • planning은 iteration 시작 전에 하고,
  • minibatch는 pipeline 간 dispatch 후 micro-batch로 나누고,
  • weight shard는 optimization 쪽에 고정된 기준을 두고,
  • pull은 forward/backward용 parameter view를 만들 때,
  • push는 gradient를 optimizer layout으로 돌려보낼 때 일어납니다.

원하시면 다음 답변에서 제가 이걸
“global minibatch → dispatch → micro-batch → pull → forward → backward → push → update”
형태로 아주 구체적인 단계별 시퀀스 다이어그램처럼 써드릴게요.

You

1. optimizer와 parallelism을 어떻게 관리하는거야? gpu 20대 있다고 하면 optimizer느 20대에 분배하고 parallelism은 뭐 TP8 하나, TP4PP2 하나, TP4하나 이런식으로 한다는거야? optimizer sharding contract가 뭐야?

Assistant

네, 방향은 맞는데 “optimizer를 20대 GPU에 따로 배분하고, parallelism은 그 위에 얹는다”라기보다는 조금 더 구조적으로 봐야 합니다.

핵심은:

  • optimizer phase는 모델 상태를 저장/업데이트하는 기준 저장소
  • propagation phase는 실제 forward/backward를 돌리는 실행용 뷰(view)
  • 이 둘을 연결하는 것이 sharding contract 입니다.

1) 큰 그림

GPU가 20대 있다고 합시다.

Hydraulis가 말하는 건 대략 이런 구조예요:

  • 20대 전체가 optimizer에만 쓰이는 게 아님
  • 전체 20대 GPU가 어떤 시점에는 propagation용 병렬 전략으로 쓰이고,
  • optimizer state는 그와 별개로 sharded state로 유지됨

즉, “GPU 20대를 optimizer용 20대 + parallelism용 20대”처럼 두 벌로 따로 쓴다는 뜻은 아닙니다.
대부분 같은 GPU 자원 위에서,

  • 어떤 조각은 parameter/optimizer state 저장에 관여하고
  • 어떤 조각은 forward/backward 병렬 실행에 관여합니다.

2) parallelism은 어떻게 잡나

사용자님 예시처럼 가능한 건 맞습니다.

예를 들어 전체 20 GPU를 여러 pipeline으로 나눠서:

  • pipeline 1: TP8
  • pipeline 2: TP4 + PP2
  • pipeline 3: TP4 같은 식으로 서로 다른 parallel scheme을 줄 수 있습니다.

다만 중요한 건:

  • 이걸 그냥 마음대로 “GPU 20대 중 일부는 optimizer, 일부는 TP”처럼 고정 분할하는 게 아니라
  • iteration마다 sequence 길이와 cost를 보고 유리한 scheme 조합을 선택할 수 있다는 점입니다.

즉, parallelism은 고정된 한 가지 layout이 아니라 전략(strategy)들의 집합입니다.


3) optimizer sharding contract가 뭐냐

이게 제일 중요합니다.

직관적으로

optimizer sharding contract는:

“propagation이 어떤 heterogeneous parallel scheme을 쓰더라도,
optimizer 쪽은 어떤 shard 단위와 질서를 기준으로 상태를 보관할지에 대한 약속”

입니다.

즉 contract는 양쪽이 맞춰야 하는 공통 규칙이에요.

  • optimizer는 자기 shard layout을 알고 있고
  • propagation은 자기 parallel layout을 알고 있는데
  • 둘이 서로 다른 layout이면 통신할 때 헷갈리죠.

그래서 Hydraulis는 ‘이 tensor는 어떤 단위로 나눠서, 어떤 순서로, 어떤 기준으로 합치거나 나눌 것인가’ 를 계약처럼 정합니다.


4) 왜 contract가 필요한가

예를 들어 parameter W가 있다고 합시다.

optimization 쪽에서는:

  • W가 shard A/B/C/D로 쪼개져 저장됨

그런데 propagation 쪽 pipeline 1은:

  • TP8 구조를 쓰고

pipeline 2는:

  • TP4+PP2 구조를 쓴다면

이 둘이 W를 바라보는 방식이 달라집니다.

그럼 문제가 생깁니다:

  • pipeline 1이 계산한 gradient를
  • optimizer 쪽 shard A/B/C/D에 어떻게 다시 맞춰 넣지?
  • pipeline 2가 pull할 때는 어떤 조각을 어디서 받아오지?

이때 필요한 공통 규칙이 sharding contract예요.


5) contract가 실제로 보장하는 것

Hydraulis의 contract는 대략 이런 역할을 합니다.

  1. parameter partition 규칙

    • 어떤 tensor를 어느 granularity로 쪼갤지
  2. gradient aggregation 규칙

    • backprop 후 gradient를 어떤 단위로 모을지
  3. reshard 가능성

    • 서로 다른 propagation 전략에서 나온 view를
    • optimizer 기준 shard로 다시 맞출 수 있어야 함
  4. 연산 순서

    • pull 전에 어떤 local movement가 필요한지
    • push 후 어떤 sync가 필요한지

즉 contract는 단순 “메모리 형식”이 아니라
통신/재배치/동기화의 규칙 전체라고 보면 됩니다.


6) 예시로 이해하기

GPU 20대가 있고, 이번 iteration에서 두 pipeline이 있다고 합시다.

  • pipeline A: TP8
  • pipeline B: TP4 + PP2

optimizer 쪽은 예를 들어:

  • parameter를 5-way shard로 유지한다고 해봅시다

그러면:

pipeline A에서 pull

  • TP8 view로 계산하려면
  • optimizer shard 5개를 받아서
  • TP8에 맞는 partition으로 재구성해야 함

pipeline B에서 pull

  • TP4+PP2 view에 맞춰
  • 같은 optimizer shard 5개를 다른 방식으로 재배열해야 함

backward 후 push

  • pipeline A/B가 계산한 gradient는
  • 다시 optimizer의 5-way shard 규칙에 맞게 합쳐져야 함

이때 contract가 없으면:

  • 누구는 길이 기준으로 자르고
  • 누구는 head 기준으로 자르고
  • 누구는 TP 기준으로 자르는 식으로 충돌이 납니다.

7) “optimizer를 20대에 분배한다”는 표현을 고치면

더 정확하게 말하면:

  • 20 GPU 전체 위에 model state sharding이 존재하고
  • 그 위에서 여러 propagation parallel strategy가 실행되며
  • pull/push가 그 둘 사이를 연결한다

입니다.

즉, optimizer는 GPU 집합 전체에 분산된 상태를 유지하는 논리 계층이고,
parallelism은 그 상태를 읽고 쓰는 실행 계층에 가깝습니다.


8) 한 줄 요약

  • parallelism: forward/backward를 어떤 TP/PP/CP 조합으로 돌릴지
  • optimizer sharding: parameter/optimizer state를 어떤 shard 규칙으로 유지할지
  • sharding contract: 이 둘이 서로 다른 view를 써도 통신과 재배치가 가능하도록 정한 공통 규칙

9) 아주 짧게 비유하면

  • optimizer sharding = 원본 창고의 선반 배치
  • parallelism = 배송팀이 물건을 꺼내는 방식
  • sharding contract = 창고-배송팀 사이의 규격서

창고가 아무렇게나 정리되면 배송팀이 못 찾고,
배송팀 방식이 바뀌어도 창고 규격이 일정해야 다시 넣을 수 있죠.


원하시면 다음 답변에서 제가
“20 GPU 예시를 넣어서 optimizer shard / TP / PP / CP / pull / push / contract가 한 iteration 동안 어떻게 돌아가는지”를 숫자 붙여서 단계별로 그려드릴게요.

You

아니 fsdp얘기하지 않았어? fsdp는 optimizer weight 들을 다 shard 하겠다는거 아냐?

Assistant

맞습니다. FSDP도 optimizer state와 parameter를 shard합니다.
제가 앞에서 너무 “Hydraulis만의 별도 optimizer 계층”처럼 말해서 헷갈리게 했네요.

정확히는:

  • FSDP/ZeRO 계열은
    • parameter
    • gradient
    • optimizer state 를 shard해서 메모리를 줄입니다.
  • Hydraulis는 그 기본 철학 위에,
    heterogeneous parallel strategy를 허용하려고 shard/reshard 규칙을 더 유연하게 만든 것에 가깝습니다.

1) FSDP가 하는 일

FSDP에서는 보통:

  • 각 rank가 parameter의 일부만 상시 보유
  • forward 전에 필요한 parameter를 all-gather
  • backward 후 gradient를 reduce-scatter
  • optimizer state도 shard

즉, 사용자의 말처럼
“optimizer weight들을 다 shard 한다”는 말은 꽤 맞습니다.
정확히는 optimizer state와 parameter를 shard한다고 보는 게 더 정확해요.


2) 그럼 Hydraulis의 차이는 뭐냐

Hydraulis도 기본적으로 이런 shard 철학을 씁니다.
그런데 일반 FSDP는 보통:

  • 모든 rank가 같은 parallel layout을 따른다
  • 즉 homogeneous하다는 가정이 강함

반면 Hydraulis는:

  • pipeline마다 TP/PP/CP 구성이 다를 수 있음
  • iteration마다 strategy가 바뀔 수 있음
  • 그래서 parameter shard를 고정된 한 가지 방식으로만 보면 안 됨

즉, Hydraulis는 “FSDP처럼 shard는 하되, propagation 전략이 달라져도 맞춰질 수 있도록 reshard를 일반화”한 것입니다.


3) 그래서 pull/push가 FSDP랑 어떻게 다른가

FSDP에서는 대체로:

  • forward 전에 필요한 parameter all-gather
  • backward 후 gradient reduce-scatter 가 비교적 고정된 패턴으로 일어납니다.

Hydraulis에서는:

  • propagation strategy가 heterogeneous할 수 있어서
  • 어떤 pipeline은 TP8, 어떤 pipeline은 TP4+PP2처럼 다를 수 있음
  • 그러니 parameter/gradient를 그 전략에 맞춰 다시 자르는 과정이 필요

이게 pull/push와 LNK입니다.

즉:

  • FSDP의 all-gather / reduce-scatter = 고정된 shard 규칙에 따른 교환
  • Hydraulis의 pull/push = 서로 다른 propagation view와 optimizer shard view를 연결하는 일반화된 교환

4) “optimizer weight를 shard한다”의 정확한 표현

엄밀히는 이렇게 말하는 게 제일 정확합니다.

  • parameter shard
  • gradient shard
  • optimizer state shard

을 유지한다.

그리고 forward/backward 시점에 필요하면 parameter를 잠깐 모으거나 재배치하고,
backward 후에는 gradient를 다시 shard layout에 맞춰 보낸다.

그래서 Hydraulis도 본질적으로는 FSDP 계열의 distributed training 철학 위에 서 있다고 볼 수 있습니다.


5) 왜 제가 전에 다르게 들렸을 수 있나

Hydraulis 논문은 단순 FSDP 설명이 아니라, “FSDP류 sharding을 heterogeneous parallelism과 결합한다”가 핵심이라서
설명을 하다 보면 optimizer state보다 pull/push로 layout을 맞추는 부분이 더 강조됩니다.

그래서 마치:

  • optimizer는 따로 있고
  • parallelism은 따로 있고
  • 중간에 뭔가 다른 계층이 있는 것처럼 들릴 수 있는데,

실제로는 FSDP처럼 shard된 모델 상태를 기준으로,
propagation 전략이 바뀔 때마다 그 상태를 맞춰주는 메커니즘을 추가한 거예요.


6) 한 문장으로 정리

네, FSDP는 parameter/optimizer state를 shard하는 방식이고,
Hydraulis는 그 위에서 heterogeneous parallel strategy에 맞게 shard를 다시 맞추는 generalized resharding/pull-push mechanism을 넣은 것입니다.


원하시면 다음 답변에서 제가
FSDP의 all-gather/reduce-scatter와 Hydraulis의 pull/push를 1:1로 대응해서 표로 정리해드릴게요.

You

10문장 안으로 대답해. 20대 gpu에 optimizer를 뿌린다는거야 안뿌린다는거야? weight는 multi-parallelism에서 알아서 분배가 되겠지? optimizer는 그래서 어떻게 한다고?

Assistant

아니요, “optimizer를 20대 GPU에 따로 뿌린다”고 이해하면 부정확합니다.
정확히는 20대 GPU 전체에 parameter/optimizer state를 shard해서 저장합니다.
즉, optimizer는 각 GPU가 일부 shard만 들고 있게 됩니다.
multi-parallelism(TP/PP/CP)은 그 shard된 weight를 어떤 방식으로 가져와서 계산하느냐의 문제입니다.
Hydraulis의 pull은 그 계산용 view에 맞게 필요한 parameter shard를 가져와 재배치하는 동작입니다.
push는 backward 후 생긴 gradient를 optimizer shard layout에 맞게 되돌리는 동작입니다.
그래서 optimizer는 따로 “뿌리는” 게 아니라, sharded state로 유지됩니다.
그리고 propagation 중에는 그 위에 다양한 병렬 전략이 pull/push로 맞춰져서 실행됩니다.
즉, weight는 parallelism이 쓰기 좋게 reshard되고, optimizer는 shard된 상태로 계속 남아 있는 구조입니다.

You

20대 gpu에 sharding해서 뿌린다는거지? parameter는 알아서 shard 재배치를 하고? gradient는 gpu p2p로 던진다는거고?

Assistant

대체로 맞지만, 몇 군데를 정확히 고치면 좋습니다.
네, 20대 GPU에 parameter/optimizer state를 shard해서 분산 보관한다고 보면 됩니다.
다만 parameter가 “알아서” 재배치되는 게 아니라, Hydraulis의 pull/LNK가 계획된 방식대로 reshard합니다.
즉, forward/backward에 필요한 shape로 parameter 조각을 모아오거나 다시 쪼갭니다.
gradient도 그냥 무작정 P2P로 던지는 게 아니라, push 단계에서 optimizer shard layout에 맞게 집계/재배치됩니다.
이 과정에는 P2P, all-gather, reduce-scatter 같은 통신이 섞일 수 있습니다.
핵심은 정해진 shard contract에 맞춰 통신한다는 점입니다.
그래서 “그냥 던진다”보다는 계획된 reshard + synchronization라고 이해하는 게 맞습니다.
요약하면, 분산 저장은 맞고, 재배치와 gradient 전송은 계획된 통신 규약에 따라 수행됩니다.

You

1. parameter 를 pull한다는건 microbatch에서 그렇게 한다는거지? 일반적으로 microbatch, 특히 parallelism이 다른 경우에는 microbatch마다 latency 차이가 커. 이것에 대해서는 어떻게 방어해? 즉, gpu20개가 3개의 parallelism을 쓴다면 각 parallelism 별로 task 종료 시간은 다 달라. 이것에 대해서 어떻게 처리할거야? 2. pipeline이란 이야기를 하는데 여기서는 pipeline parallelism 에 대한 이야기가 아니지? 뭐에대한 pipeline이야?

Assistant
  1. 맞아요, pull은 실행 단위에 붙어서 일어나는 동작이라서 보통은 micro-batch를 처리할 때 필요한 시점에 parameter를 가져오는 것으로 이해하면 됩니다.
    Hydraulis는 이 latency 차이를 그냥 방치하지 않고, pipeline 내부 packing + pipeline 간 dispatch + heterogeneous strategy 선택으로 micro-batch별 실행 시간을 최대한 비슷하게 맞추려 합니다.
    즉, 20 GPU가 3개의 parallelism을 쓰면 각 task 종료 시간이 달라지는 문제를 인정하고, 길이/비용 예측 후 비슷한 latency를 갖는 sequence들을 같은 전략에 묶는 식으로 방어합니다.
    그래서 micro-batch마다 생기는 편차는 sequence assignment과 packing 단계에서 먼저 줄이고, 남는 통신은 subgraph로 묶어 overlap합니다.
    완전히 없애는 건 아니고, 가장 느린 micro-batch가 전체를 끌고 가는 상황을 최소화하는 게 목표입니다.

  2. 여기서 말하는 pipeline은 일반적인 “pipeline parallelism” 자체만을 뜻하는 게 아니라,
    서로 다른 parallel scheme을 가진 실행 파이프라인들을 뜻하는 쪽에 가깝습니다.
    즉, 하나의 글로벌 모델을 여러 stage로 나눈 전통적 PP만이 아니라, 각 stage/worker 그룹이 자기 TP/PP/CP 조합으로 하나의 실행 경로를 구성하는 단위예요.
    논문에서는 이 pipeline들 사이에 sequence dispatch를 하고, pipeline 내부에서는 packing을 하며, 필요할 때 pull/push를 넣습니다.
    그래서 여기서 pipeline은 “모델 stage”라기보다 하나의 병렬 전략 인스턴스로 이해하는 게 더 정확합니다.

원하시면 다음엔 제가 “micro-batch latency 불균형을 Hydraulis가 어디서 줄이고, 어디서 못 줄이는지”를 아주 짧게 도식으로 정리해드릴게요.

You

1. subgraph라는게 무슨소리야? pull parameter, push gradient, communicate activation 이 세개의 operation을 그냥 subgraph라고 명명하는거야? 2. microbatch를 packing을 하고, 그러고 나서 parallelism을 정하는거야? 그러면 뭐로 자르는거야? packing을 어떻게해?

Assistant
  1. 완전히 그냥 이름만 붙인 건 아니고, 이 세 가지 통신 관련 연산을 별도의 그래프 조각으로 분리해서 다루는 개념입니다.
    즉, Pull Parameter, Push Gradient, Communicate Activation은 subgraph의 유형/역할이지, 아무 연산이나 다 subgraph라고 부르는 건 아닙니다.
    논문 의도는 계산 그래프에서 통신 때문에 생기는 부분만 떼어내서, scheduler가 그걸 독립된 단위처럼 보고 계산과 overlap하게 만들자는 것입니다.
    그래서 subgraph는 “작은 그래프”라는 말보다 통신 경로를 캡슐화한 실행 단위에 가깝습니다.

  2. 순서는 parallelism을 먼저 정하고 packing을 나중에 하는 것에 더 가깝습니다.
    먼저 데이터 길이 분포를 보고, 어떤 parallel strategy 후보가 가능한지 정한 뒤, 그 전략들에 맞춰 sequence들을 pipeline에 dispatch합니다.
    그 다음 각 pipeline 안에서 그 sequence들을 micro-batch로 packing합니다.
    packing은 보통 sequence length와 cost model을 기준으로, 한 micro-batch의 총 실행 시간이 비슷해지도록 묶는 방식입니다.
    즉 “무엇으로 자르냐”는 질문에 대한 답은 sequence 단위입니다.
    길이와 MaxLen(P) 제약을 보고, 같은 pipeline/strategy 안에서 여러 sequence를 한 micro-batch에 넣되, 가장 긴 sequence가 latency를 지배하지 않도록 조합합니다.
    이걸 논문은 ILP/근사해로 풀어서, pipeline 내부의 packing과 pipeline 간 dispatch를 따로 최적화합니다.
    요약하면 sequence들을 기준으로 자르고, strategy를 먼저 고르고, 그 strategy 안에서 packing합니다.

You

1. 데이터 길이 분포를 보고 parallelism strategy를 정하는 알고리즘을 설명해줘.

Assistant

네. 논문에서의 핵심은 “현재 데이터 길이 분포에 대해, 어떤 parallel strategy가 기대 비용을 최소화하는가”를 먼저 고르는 것입니다.
전개는 대략 3단계입니다.

  1. 후보 strategy 공간을 만든다
    각 pipeline의 parallel scheme 조합을 strategy로 보고, 가능한 조합들 중에서 MaxLen(P)를 만족하는 것만 남깁니다.
    즉, 어떤 strategy는 긴 sequence를 못 버티면 후보에서 제외됩니다.

  2. 길이 분포를 비용으로 바꾼다
    길이 구간별 데이터 분포 D를 가지고, 각 strategy P에 대해
    T(l, P) 같은 profiling된 latency 모델로 기대 실행 비용을 계산합니다.
    직관적으로는 “이 데이터 길이 분포에서 이 strategy를 쓰면 평균적으로 얼마나 빨리 도나?”를 점수화하는 겁니다.

  3. 최소 비용 strategy를 찾는다
    이걸 처음에는 단순화해서, 각 pipeline이 담당할 길이 interval을 정하는 형태로 바꾸고,
    동적 계획법(DP)으로 최적 strategy를 구합니다.
    그 다음 continuous relaxation으로 정수 제약을 풀어 더 넓은 해를 찾고,
    마지막에 rounding해서 실제 쓸 수 있는 candidate strategy set Ŝ를 만듭니다.

즉, 알고리즘의 핵심은
“길이 분포 → 길이별 기대 latency → strategy별 총 기대 비용 → DP/relaxation/rounding으로 후보 추림” 입니다.

아주 직관적으로 말하면:

  • 짧은 sequence가 많으면, 짧은 쪽에 강한 strategy를 더 유리하게 보고
  • 긴 sequence가 섞이면, 메모리를 덜 쓰는 strategy를 포함시키고
  • 최종적으로는 분포 전체에서 평균 비용이 가장 낮은 strategy 조합을 선택합니다.

원하시면 다음 답변에서 이걸 간단한 숫자 예시로 DP가 어떻게 돌아가는지까지 보여드릴게요.

You

1. maxlen P는 뭔소리야? 짧은 sequence는 작은 parallelism에서 해야하고 긴건 큰 parallelism에서 처리할 텐데 다 서로다른 sequence length를 가지고 있고, 그런데 여기서 뭘 제외하겠다는거야? 제외하는건 short parallelism 최적화 기회를 잃는거 아니야?

Assistant

MaxLen(P)는 “전략 P가 버틸 수 있는 최대 sequence length”를 뜻합니다.
즉, 어떤 parallel scheme은 메모리/통신/activation 때문에 너무 긴 sequence를 처리하면 안 되는 한계가 있습니다.
그래서 l > MaxLen(P)이면 그 sequence는 아예 그 strategy 후보에 넣을 수 없다는 뜻입니다.

중요한 건, 이건 짧은 sequence 최적화 기회를 버린다는 뜻이 아닙니다.
오히려 반대예요: 짧은 sequence는 더 많은 strategy 후보를 가질 수 있고, 긴 sequence는 선택지가 줄어듭니다.
예를 들어 짧은 sequence는 TP가 큰 빠른 strategy도 가능하고, 긴 sequence는 메모리 때문에 TP가 작은 느린 strategy만 가능할 수 있습니다.
그래서 MaxLen(P)는 “이 strategy가 처리 가능한 길이의 상한” 이지, 모든 sequence를 한 strategy로 통일한다는 뜻이 아닙니다.

논문에서 strategy proposal을 하는 이유는, 모든 가능한 조합을 전부 탐색하지 않고도
“각 길이에 대해 현실적으로 가능한 strategy들”만 남겨서 후보를 줄이려는 것입니다.
즉, 제외되는 건 short 최적화 기회가 아니라, 물리적으로 불가능하거나 너무 비싼 strategy입니다.

한 줄로 말하면:

  • 짧은 sequence: 후보 strategy가 많음
  • 긴 sequence: 후보 strategy가 적음
  • MaxLen(P)는 그 후보 가능 여부를 가르는 feasibility bound 입니다.
You

아 1. sequence length마다 viable strategy를 전부 정리 2. 각 sequence length마다 offline profile 기반 D,P 로 T 생성 3. 그리고 DP? DP 규칙이 어떻게 되는거지?

Assistant

네, 거의 맞게 잡으셨습니다.
정리하면:

  1. 길이별 viable strategy를 본다
  2. offline profile로 각 길이-전략 조합의 latency T(l, P)를 만든다
  3. 그걸 바탕으로 DP로 strategy를 고른다

DP의 핵심 규칙은 “길이 구간을 어떻게 나눠서, 각 구간을 어떤 strategy가 맡게 할 것인가”입니다.


DP의 상태

논문 식을 아주 직관적으로 바꾸면,
길이 구간 [0, L]을 여러 조각으로 나누고, 각 조각에 대해 최적 strategy를 고르는 문제입니다.

예를 들어:

  • 0~512
  • 513~1024
  • 1025~4096

같이 구간을 나눈다고 생각하면 됩니다.


DP의 점화 아이디어

어떤 구간의 끝 L에 대해,

  • L까지의 최적 비용 =
    어떤 중간 분할점 k를 고르고
  • [0, k]까지의 최적 비용 +
  • [k+1, L] 구간을 어떤 strategy P로 처리할 때의 비용

중 최소를 택하는 방식입니다.

즉, 전형적인 interval partition DP입니다.


비용은 무엇인가

구간 [a, b]를 strategy P가 맡을 때의 비용은, 그 구간에 속한 sequence들이 그 strategy에서 처리될 때의 기대 latency입니다.
이 기대값은 dataset 분포 D와 profiling된 T(l, P)를 이용해 계산합니다.

즉 대충:

  • “이 길이 구간의 데이터가 얼마나 자주 나오나”
  • “이 strategy가 그 길이를 처리하는 데 얼마나 걸리나” 를 곱해서 누적합니다.

직관

DP는 결국 이런 질문을 푸는 겁니다:

“짧은 길이 구간은 빠른 strategy A에 맡기고,
중간 길이는 strategy B에 맡기고,
긴 길이는 메모리 안전한 strategy C에 맡길 때,
전체 기대 비용이 최소가 되는 구간 분할은 무엇인가?”


왜 DP가 필요하냐

단순히 “각 길이에 대해 가장 빠른 strategy”만 고르면 안 됩니다.
왜냐하면:

  • 전략마다 coverage가 다르고
  • 한 strategy를 너무 많이 쓰면 다른 길이 구간에서 손해가 나고
  • 전체 분포 기준으로는 구간을 묶어서 보는 게 유리할 수 있기 때문입니다.

그래서 DP로 구간 분할 + strategy 할당을 같이 최적화합니다.


한 줄 요약

DP는
“길이 구간을 어디서 자를지 + 각 구간을 어떤 viable strategy가 맡을지”를 최소 기대 latency 기준으로 고르는 interval partitioning DP입니다.

원하시면 다음 답변에서 제가
아주 작은 예시(길이 4개, strategy 2개)로 DP 테이블이 어떻게 채워지는지 보여드릴게요.

You

내가 알고리즘을 잘 이해를 못한 거 같은데, 1. 길이별 strategy를 보고 2. length 별로 DP를 분리 3. 그리고 strategy최적화? 이게 DP로 모델링이 돼? 가능한 부분은 datum packing이잖아. 이걸 DP로 처리하겠다느거야? 예시 보여줘.

Assistant

맞아요. 지금 혼동한 핵심은 “strategy 선택”과 “packing”이 서로 다른 단계라는 점입니다.
제가 더 정확히 말하면, 논문에서 DP는 주로 packing/dispatch 후보를 고르는 문제에 쓰이고,
“strategy 자체를 DP로 직접 최적화한다”기보다는 strategy별 비용을 이미 profiling해 두고 그 비용을 기준으로 배치 문제를 푼다에 가깝습니다.

1) 역할 분리

  • strategy proposal:
    길이 분포를 보고, 각 길이에 대해 viable한 parallel strategy 후보를 추립니다.
  • packing / dispatch optimization:
    그 후보 strategy들을 가지고 sequence들을 어디에 어떻게 넣을지 계산합니다.
  • DP:
    이때 길이 구간을 나누거나, sequence를 순서대로 묶는 partitioning에 사용됩니다.

즉, DP가 “parallel strategy를 새로 발명”하는 게 아니라,
이미 있는 strategy들 중 어떤 길이 구간에 어떤 걸 쓸지를 고르는 계산이에요.


2) 아주 작은 예시

sequence length가 4개 있다고 합시다:

  • s1 = 100
  • s2 = 200
  • s3 = 800
  • s4 = 1200

viable strategy가 2개 있다고 해봅시다:

  • P1: 빠르지만 긴 sequence는 못 버팀 (MaxLen(P1)=1000)
  • P2: 느리지만 긴 sequence도 가능 (MaxLen(P2)=2000)

profiling latency는 대충:

  • T(100, P1)=1, T(200, P1)=1.2, T(800, P1)=3
  • T(100, P2)=1.5, T(200, P2)=1.7, T(800, P2)=2.8, T(1200, P2)=4

그러면:

  • s1,s2,s3는 P1이나 P2 가능
  • s4는 P2만 가능

3) packing을 DP로 어떻게 보냐

예를 들어 한 pipeline 안에서 micro-batch를 2개로 나누고 싶다고 합시다.
그러면 sequence를 두 묶음으로 partition해야 합니다.

가능한 분할:

  • [100,200] / [800,1200]
  • [100] / [200,800,1200]
  • [100,200,800] / [1200]
  • ...

각 묶음의 비용은 그 묶음 안에서의 가장 느린 sequence latency 또는 packing cost model로 계산합니다.
DP는 이런 식으로:

  • 앞에서부터 sequence를 하나씩 보면서
  • “여기서 끊을까, 더 묶을까?”를 비교해서
  • 전체 비용이 최소가 되는 partition을 찾습니다.

4) 직관적인 DP 상태

dp[i] = 첫 i개 sequence를 packing했을 때의 최소 비용

점화식은:

  • dp[i] = min over j<i { dp[j] + cost(j+1..i) }

여기서 cost(j+1..i)는

  • 그 구간을 하나의 micro-batch로 묶었을 때의 latency
  • 그리고 그 구간에 쓸 수 있는 viable strategy 중 최선의 비용

입니다.

즉 DP가 하는 일은:

  1. sequence들을 어디서 자를지 정하고
  2. 각 조각에 대해 viable strategy 중 cheapest한 걸 고르는 것

입니다.


5) 그럼 strategy는 어디서 고르냐

strategy는 DP가 “새로 만드는” 게 아니라, 각 구간 비용을 계산할 때 후보로 들어갑니다.

예를 들어 구간 [800,1200]은:

  • P1은 1200 못 버팀 → 불가능
  • P2만 가능 → P2 비용 사용

구간 [100,200]은:

  • P1 가능, P2 가능
  • 둘 중 더 싼 걸 고름

이런 식으로요.


6) 핵심을 한 줄로

DP는 strategy 탐색기가 아니라, packing/partition optimizer입니다.
strategy는 이미 profiling으로 후보가 정해져 있고,
DP는 그 후보들을 이용해 sequence를 어디서 끊고 어떤 묶음을 만들지 계산합니다.


원하시면 다음 답변에서 제가
dp[0..4]를 실제 숫자로 채워가는 표 형태 예시를 만들어 드릴게요.

You

1. micro batch를 100개로 나누고 싶은 상황은 어떻게 처리한다는거지? 2. DP로 해결해야할 것은, 1. 어디부터 어디까지 묶을 것인가. 2. 어디부터 어디까지 묶어서 다음 parallelism까지 적용할것인가. 3. 어떤 parallelism이 다른 parallelism보다 superior하게 좋다. 예를들어서, short sequence 면 무조건 TPCPPP 111 로 가져가는게 최선이다. 이런 규칙이 있지 않는이상, 어떤 것이 다른 것보다 더 좋다고 만드는 logic이 부족해보여.

Assistant
  1. micro-batch를 100개로 나누고 싶다면, Hydraulis 관점에서는 먼저 global minibatch 안의 sequence들을 100개 실행 단위로 쪼개는 제약을 둡니다.
    그러면 packing/dispatch는 그 100개 slot에 sequence들을 배치하는 문제로 바뀝니다.
    논문식으로는, micro-batch 개수를 V처럼 두고 그 조건 아래에서 각 slot의 최대 latency를 최소화하도록 묶습니다.
    즉 “100개로 반드시 나눈다”는 건 외부 제약이고, DP/ILP는 그 제약 안에서 어떤 sequence를 어느 slot에 넣을지를 찾습니다.

  2. 당신이 정리한 DP 대상은 거의 맞는데, (3)은 논문이 명시한 ‘절대 우월한 규칙’이 아니라 cost model 기반 선택입니다.
    즉 “short면 무조건 TPCPPP 111” 같은 하드코딩 규칙은 없고,
    대신 각 strategy의 T(l, P)와 MaxLen(P)를 profiling해 두고, 길이 l에서 누가 더 싼지를 비교합니다.
    그래서 어떤 strategy가 다른 것보다 superior하다는 건 특정 길이/메모리 제약/통신 조건에서의 비용 우위로 정의됩니다.
    short sequence라고 해도, 특정 하드웨어나 병렬 조합에서는 다른 strategy가 더 나을 수 있어서 하드 rule은 두지 않습니다.
    논문의 로직은 “우월한 전략의 보편 규칙”이 아니라 구간별 최저 비용 전략을 찾는 최적화예요.
    따라서 부족해 보이는 부분은 맞고, 그 공백을 메우는 것이 바로 profiling 기반 cost model + DP/ILP입니다.
    결론적으로, Hydraulis는 ‘무조건 이 전략’이 아니라 ‘이 길이와 제약에서 가장 싼 전략’을 고르는 방식입니다.

You

내가 하고 싶은 말은, 개별 sequence length에서는 low parallelism 전략이 우월할 수 있어도, packing을 하게 되면 그렇지 않을 수 있따는거야. 그런데 각 sequence 별로 parallelism 제약을하고 거기서 길이 l에서 뭐가 더싼지 비교한다는게, 그러니까 cost(X) + cost(Y) > cost(X+Y)인 상황아니냐는거야.

Assistant

맞습니다. 그 지점이 핵심이고, 그냥 sequence별로 최싼 strategy를 고르는 방식이면 packing의 이득을 놓칩니다.
당신이 말한 cost(X) + cost(Y) > cost(X+Y) 상황이 바로 packing이 존재하는 이유예요.

Hydraulis가 보는 비용은 단순히 “각 sequence를 따로 돌릴 때의 합”이 아니라, 같은 strategy/같은 micro-batch로 묶었을 때의 공동 비용입니다.
즉 T(l, P)는 개별 sequence의 독립 실행 비용이라기보다, 그 길이의 sequence를 그 strategy에서 처리할 때의 cost model이고, packing 단계에서는 여러 sequence를 한 micro-batch에 넣었을 때의 cost를 따로 계산합니다.

그래서 올바른 비교는:

  • sequence A를 따로,
  • sequence B를 따로
    돌리는 비용의 합 vs.
  • A와 B를 같은 micro-batch로 packing했을 때의 비용

입니다.
이 비교에서 packing이 이득이면, DP/ILP는 당연히 묶는 쪽을 고릅니다.

즉, Hydraulis는 “길이 l에서 어떤 strategy가 더 싸냐”만 보는 게 아니라,
“여러 sequence를 어떤 strategy 아래 어떤 묶음으로 만들면 총 latency가 최소냐”를 봅니다.

당신의 비판은 타당하고, 만약 이 모델이 T(l,P)만으로 결정된다면 packing의 상호작용을 놓칠 수 있습니다.
그래서 논문이 실제로는 pipeline 내부 packing 비용 모델과 pipeline 간 dispatch를 별도로 둡니다.
한마디로, cost(X)+cost(Y)와 cost(X+Y)의 차이를 packing objective가 직접 다룬다고 이해해야 합니다.

You

아 그냥 DP 예씨를 들어서 설명해줘. hydraulis가 이걸 처리한다는거야 만다는거야?

Assistant

처리합니다. 다만 “sequence마다 전략을 독립적으로 고른다”가 아니라, “묶음(packing) 자체를 최적화”하는 방식으로 처리합니다.

아주 작은 예시로 볼게요.

예시

sequence 4개가 있습니다.

  • A = 길이 100
  • B = 길이 120
  • C = 길이 500
  • D = 길이 520

가능한 strategy는 2개라고 합시다.

  • P1: 짧은 sequence에 빠름
  • P2: 긴 sequence에도 가능하지만 좀 느림

그리고 packing 후 비용은 대충:

  • A와 B를 따로 돌리면 각 1, 1
  • A+B를 한 micro-batch로 묶으면 1.5
  • C와 D를 따로 돌리면 각 4, 4
  • C+D를 한 micro-batch로 묶으면 5.5
  • P1은 520까지는 못 버팀
  • P2는 다 가능

DP가 보는 선택

첫 두 개 A,B에 대해:

  • 따로 처리: 1 + 1 = 2
  • 같이 묶기: 1.5

→ DP는 같이 묶는 쪽을 선택할 수 있습니다.

C,D에 대해서도:

  • 따로 처리: 4 + 4 = 8
  • 같이 묶기: 5.5

→ 이것도 같이 묶는 쪽을 선택합니다.


그런데 strategy는?

A,B를 묶는 micro-batch는 P1이 더 싸다고 합시다.
C,D를 묶는 micro-batch는 P2만 가능하다고 합시다.
그러면 DP는:

  • [A,B]는 P1으로 하나의 묶음
  • [C,D]는 P2로 하나의 묶음

으로 결정합니다.

즉, sequence별로 strategy를 따로 최적화하는 게 아니라, 묶음 단위로 strategy를 고릅니다.


Hydraulis가 처리하는가?

네, 처리합니다.
하지만 방식은:

  1. sequence를 보고
  2. packing 후보를 만들고
  3. 그 packing마다 가능한 strategy 비용을 비교해서
  4. 최종 묶음/전략을 고르는 것

입니다.


핵심 한 줄

Hydraulis는 cost(X)+cost(Y)를 직접 보는 게 아니라,
X,Y를 따로 둘지, 같이 묶을지, 그리고 그 묶음에 어떤 strategy를 쓸지`를 DP로 고릅니다.

원하시면 제가 다음 답변에서 진짜 DP 테이블 형태로 dp[1], dp[2], dp[3], dp[4]를 계산하는 예시를 써드릴게요.`

You

ABCD에 대해서 bst microbatch 수는 어떻게 정하는거야? 2,3,4, 이런건 임의로 정해? 1. 결과적으로 비교해야하는건, strategy가 2개라는건 진짜 멍청한소리고,strategy는 한 100개정도 봐야해 대충. 그러면, AB를 묶는 strategy, ABC를 묶는 것, ABCD를 묶는 것, BC를 묶는 것, BCD를 묶는 것, CD를 묶는 것, 그리고 각 묶음에 따른 모든 strategy lookup을 진행해야해. 이렇게 한다는게 맞아?

Assistant

네, 거의 맞는데 중요한 보정이 하나 있습니다.
Hydraulis가 전수로 AB, ABC, ABCD, BC…를 전부 다 보는 건 이론적으로는 그럴 수 있지만, 실제로는 그렇게 무식하게 다 하진 않으려는 쪽입니다.

1) micro-batch 수는 임의인가?

아니요. 임의가 아니라 실행 제약과 목표에 따라 정합니다.
논문에서는 micro-batch 개수 V를 두고, 그 V 아래에서 가장 큰 latency를 최소화하는 식으로 packing을 풉니다.
즉 V=2,3,4를 아무렇게나 고르는 게 아니라,

  • 메모리
  • pipeline bubble
  • 계산 균형
  • throughput 목표
    를 고려한 문제의 제약/설정값입니다.

2) strategy가 100개라면, 묶음마다 다 비교하나?

큰 틀에서는 맞습니다.
각 가능한 묶음에 대해:

  • 그 묶음이 어느 strategy에서 feasible한지 보고
  • feasible한 strategy들 중 비용이 가장 낮은 걸 찾습니다.

즉 AB, ABC, ABCD, BC, BCD, CD 같은 구간 후보가 있고,
각 구간에 대해 strategy 100개를 돌려서 cost를 비교하는 느낌이 맞습니다.

3) 그런데 전부 전수탐색하나?

여기가 핵심인데, 논문은 이걸 직접 전수탐색하기보다 DP / ILP / approximate method로 압축해서 푼다는 쪽입니다.
그래서 개념적으로는:

  • 모든 연속 구간 후보를 고려하고
  • 각 구간마다 가능한 strategy를 평가하고
  • 전체 비용이 최소가 되게 고름

이지만, 구현은 모든 조합을 완전 열거하는 것보다 훨씬 작게 줄이려는 구조입니다.

4) 당신이 말한 방식이 맞는지

네, 문제 정의 차원에서는 맞습니다.
즉 Hydraulis가 풀어야 하는 건 정말로:

  • 어떤 sequence들을 한 묶음으로 만들지
  • 그 묶음에 어떤 strategy를 쓸지
  • 그 결과 전체 latency가 얼마나 되는지
    를 비교하는 문제예요.

다만 실제로는 100개 strategy × 모든 구간 조합을 brute force로 다 돌리는 건 아니고,
DP가 구간 분할을, profiling이 strategy cost lookup을, 그리고 후보 축소가 탐색 공간을 줄입니다.

5) 한 줄 결론

  • micro-batch 개수는 임의가 아니라 제약/목표에 따라 정함
  • 전략이 많으면 구간별 strategy lookup을 하는 건 맞음
  • 하지만 논문은 그걸 brute force가 아니라 DP/approximation으로 푼다

원하시면 제가 다음 답변에서
“ABCD에 대해 실제 DP 상태가 어떻게 돌아가는지, strategy 100개를 가진다고 가정한 의사코드”로 써드릴게요.

You

1. 구간 후보는 어떻게 정하는거야? 2. micro batch는 메모리 pipeline bubble 계산 균형 throughput에 따라 정한다는데 그래서 정하는 알고리즘이 뭐야?

Assistant
  1. 구간 후보는 보통 sequence를 원래 정렬된 순서 그대로 연속 구간으로만 봅니다.
    즉 ABCD가 있으면 후보는 A|BCD, AB|CD, ABC|D 같은 contiguous partition이지, AC나 BD처럼 임의 조합을 다 보진 않습니다.
    이게 DP가 가능한 이유예요.
    각 구간의 cost는 그 구간을 하나의 micro-batch로 넣었을 때의 latency를 뜻하고, feasible strategy들 중 최저 cost를 lookup합니다.
    그래서 후보는 “모든 subset”이 아니라 연속된 interval입니다.

  2. micro-batch 개수 정하는 알고리즘은 논문에서 한 마디로 “제약을 만족하는 범위에서 throughput/bubble을 고려해 정한다”에 가깝고,
    구체적으로는 미리 정한 micro-batch 수 V에 대해 최적 packing을 푸는 방식으로 읽는 게 맞습니다.
    즉 보통은 V를 후보로 두고, 각 V에 대해:

    • 메모리 제약을 넘지 않는지 확인하고
    • pipeline bubble이 (PP-1+V)처럼 반영된 비용을 계산한 뒤
    • 전체 latency가 최소가 되는 V/packing을 고릅니다.

    더 쉽게 말하면,
    “micro-batch 수를 먼저 아무렇게나 정하는” 게 아니라, 가능한 V들에 대해 packing cost를 계산해서 제일 좋은 걸 고르는 최적화 문제입니다.
    그래서 알고리즘 자체는 interval DP / ILP 기반 packing이고, V는 그 최적화의 후보 변수에 가깝습니다.

원하시면 다음 답변에서 제가 ABCD 예시로 V=2와 V=3을 비교하는 숫자 그림을 보여드릴게요.

You

1. AC나 BD가 불가능한 이유에 대해서 설명해? 예를들어서, 1,2, 1000,1001 이면, 1,2 합쳐서 할게 아니라 1001+1, 1000+2 로 하면 훨씬 빠르잖아?

Assistant

맞습니다. AC, BD 같은 비연속 pairing이 항상 불가능한 건 아니고, 오히려 더 좋을 수도 있습니다.
제가 앞에서 “연속 구간만 본다”라고 말한 건 너무 단순화한 설명이었습니다. Hydraulis의 실제 문제는 sequence의 원래 순서를 무조건 유지하는 partition만 보는지, 아니면 dispatch 단계에서 재배치까지 허용하는지를 구분해야 합니다.

당신이 든 예시 1,2,1000,1001에서는

  • (1,1001)
  • (2,1000)
    처럼 비슷한 총 비용끼리 pairing하는 게 훨씬 유리할 수 있습니다.
    이건 packing 관점에서 아주 자연스러운 지적입니다.

Hydraulis에서는 이걸 pipeline 간 dispatch 단계에서 다룹니다.
즉:

  • pipeline 내부 packing은 보통 한 pipeline에 배정된 sequence들 안에서 묶는 문제이고,
  • pipeline 간 dispatch는 어떤 sequence를 어떤 pipeline에 넣을지를 재배치하는 문제입니다.

그래서 AC, BD 같은 pairing이 “금지”라기보다,
어떤 pipeline에 어떤 sequence를 넣느냐를 먼저 정해서 가능한 조합을 만든다고 보는 게 맞습니다.
그 뒤에 pipeline 내부에서 packing을 수행합니다.

즉 당신 예시처럼:

  • 긴 것과 짧은 것을 섞는 재배치가 유리하면
  • dispatch가 그걸 찾아야 하고
  • packing은 그 결과를 받아 micro-batch를 형성합니다.

정리하면:

  • 비연속 pairing이 원천 금지인 건 아님
  • 오히려 그게 유리할 수 있음
  • Hydraulis는 그걸 dispatch + packing으로 다루는 쪽입니다

원하시면 다음 답변에서 제가
“dispatch 단계에서 재배치가 어디까지 허용되는지”를 예시로 더 정확히 풀어드릴게요.

You

hydraulis가 이걸 어떻게 DP로 푼다는거야? 내가 아는 DP가 맞나? 내가 생각한건, ABC가 있을 때 최선을 찾음. D가 들어옴. ABCD가 있을 때 최선을 찾는데, ABC에 대한 데이터를 참고함. 이런 점화식과 같은 규칙이 가능해야 찾을 수 있다고 생각하는데, 실제로는 이걸 활용해서 찾을 수 있는 유일한 경우는 ABC (알아서 microbatching)/ D 추가. 이 경우에만 활용할 수 있는거 아니야? AD, CD 이런식으로 섞어서 하면, 뭐 CD는 가능하겠다. AB에 대해서 처리가 되어있을테니까. AD 도 마찬가지네 BC에 대해서 처리가 되어있을테니까. 대충 이해한 것 같아.

Assistant

네, 지금 이해하신 방향이 훨씬 더 맞습니다.
당신이 떠올린 DP는 거의 맞고, 핵심은 “앞에서부터 누적된 prefix 최적해를 이용해 다음 원소를 붙일지, 어디서 끊을지”입니다.

Hydraulis가 DP로 푸는 건 대체로 이런 형태예요:

  • ABC까지의 최적 packing/dispatch가 있고
  • D가 새로 들어오면
  • ABCD의 최적해는
    • ABC | D
    • AB | CD
    • A | BCD 같은 분할 후보들 중 최저 비용을 고르는 방식입니다.

즉, DP는 “이미 계산한 prefix 결과를 재사용하면서, 현재까지 본 sequence들의 최적 partition을 확장”하는 겁니다.


왜 AD, CD 같은 것도 가능한가

맞습니다.
예를 들어 ABCD에서:

  • AB는 앞에서 최적화된 부분을 재사용할 수 있고
  • CD는 뒤쪽 새 구간에 대한 선택입니다.

그래서 DP는 보통:

  • 이전 prefix의 최적값
  • 그리고 새 구간의 비용

을 합쳐서 더 나은 분할을 찾습니다.


당신이 말한 “섞어서 하면 안 되나?”

이건 가능한 경우와 아닌 경우를 구분해야 합니다.

  • DP가 보는 건 보통 순서를 유지한 연속 분할입니다.
  • A,D를 묶고 B,C를 묶는 식의 완전 재배열은,
    만약 논문이 그냥 interval DP만 쓴다면 직접 못 봅니다.
  • 그런 재배열은 보통 dispatch 단계에서 누가 어느 pipeline으로 가는지 재배치하는 쪽이 담당합니다.

즉:

  • DP = 주어진 순서 안에서 어떻게 자를지
  • dispatch = 어떤 sequence를 어느 pipeline에 보낼지

로 나뉘는 거예요.


그래서 당신이 정리한 이해는?

거의 맞습니다. 다만 한 가지를 덧붙이면:

Hydraulis의 DP는 “모든 가능한 섞기”를 다 보는 DP가 아니라,
이미 정렬되거나 배정된 sequence 집합 안에서 최적 분할을 찾는 DP에 가깝습니다.

그래서 AB, CD는 쉽게 다룰 수 있지만,
AD, BC 같은 재배치는 별도의 dispatch/assignment 문제로 올라갑니다.


한 줄 요약

네, 당신이 말한 것처럼 DP는 prefix 최적해를 재사용하면서 다음 구간을 붙이거나 자르는 방식이고,
AD/BC처럼 섞는 건 DP 자체보다 dispatch/assignment 단계의 문제입니다.

원하시면 다음 답변에서 제가
“DP가 보는 것 vs dispatch가 보는 것”을 구분해서 아주 짧게 도식화해드릴게요.

You

DP를 사용하는거 꽤 합리적이어 보인다. AD/BC는 왜 DP문제가 아니야? DP에서 이렇게 정하면 dispatch도 이렇게 해야하는거 아니야?

Assistant

맞아요, 그렇게 보일 수 있습니다.
그리고 어떤 의미에서는 dispatch도 DP의 일부로 묶어서 볼 수 있습니다.
다만 논문이 문제를 나누는 방식은 보통 이렇습니다:

  1. dispatch

    • sequence를 어떤 pipeline/strategy 그룹에 보낼지 정함
    • 여기서 AD/BC처럼 서로 다른 길이의 조합을 만들 수 있음
  2. packing

    • 각 그룹 안에서 micro-batch를 어떻게 묶을지 정함
    • 이때는 보통 연속된 작업 단위나 그룹 내부의 순서를 기준으로 DP를 씀

왜 AD/BC가 별도처럼 보이냐

AD/BC는 단순히 “어디서 자를까” 문제가 아니라, 누가 누구와 같이 묶일지를 먼저 정해야 하는 문제입니다.
이건 사실 assignment/partitioning 문제에 더 가깝습니다.

반면 packing DP는 보통:

  • 이미 정해진 sequence들의 순서 또는 후보 집합이 있고
  • 그 안에서 최적 분할점을 찾는 문제입니다.

즉,

  • dispatch = 그룹을 만드는 문제
  • DP packing = 그룹 내부를 최적 분할하는 문제

로 분리해서 생각하면 됩니다.


그런데 둘이 연결되지 않나?

물론 연결됩니다.
dispatch가 A,D와 B,C를 고르면, 그 다음 packing DP는 그 선택된 그룹 안에서만 최적화를 합니다.
그래서 dispatch 결과가 바뀌면 DP 입력도 바뀌죠.

즉:

  • dispatch가 상위 레벨에서 “조합”을 정하고
  • DP가 하위 레벨에서 “묶는 방식”을 정합니다.

왜 이런 분리가 합리적이냐

모든 가능한 AD/BC, AB/CD, AC/BD를 한 번에 DP로 풀면 상태공간이 너무 커집니다.
그래서 논문은 보통:

  • 상위에서 가능한 strategy/pipeline 후보를 줄이고
  • 하위에서 packing을 최적화하는 식으로 계층화합니다.

결론

  • AD/BC도 넓게 보면 DP의 대상일 수는 있습니다.
  • 하지만 논문 구조상 보통은 dispatch(assignment) 와 packing DP를 분리합니다.
  • 그래서 “DP에서 정하면 dispatch도 그에 맞춰야 한다”는 말은 맞고,
    다만 실제론 dispatch가 먼저, packing DP가 그 다음이라고 보는 편이 더 정확합니다.

원하시면 제가 다음 답변에서
Hydraulis를 “assignment DP + packing DP” 두 층으로 나눠서 숫자 예시로 설명해드릴게요.

You

아 DP로는 microbatch를 자르고, 예를들어서 ABC/D를 하면 ABC를 처리하는 시간이랑 D를 처리하는 시간이랑 balancing이 된다는거야? 그리고 각 microbatch 내에선 또 서로 다른 parallelism으로 처리하고? 이 값들은 사실 DP에서 다 처리를 해서 dispatch만 잘하면 되는 방향이겠지?

Assistant

네, 큰 방향은 거의 맞습니다.
Hydraulis에서 DP가 주로 하는 일은 어떤 sequence들을 한 micro-batch로 묶을지를 정해서, micro-batch들 사이의 처리 시간을 최대한 비슷하게 맞추는 것입니다.
그래서 ABC / D로 자르면, 이상적으로는 ABC micro-batch의 처리시간과 D micro-batch의 처리시간이 균형에 가깝게 되도록 고르는 거예요.

그리고 각 micro-batch 안에서는, 그 micro-batch에 배정된 sequence 길이와 메모리 제약에 맞는 parallelism strategy를 선택해서 처리합니다.
즉 “micro-batch를 자른 뒤에, 그 묶음에 맞는 parallelism을 고른다”는 이해가 맞습니다.

다만 아주 중요한 점이 하나 있는데,
이 값들이 전부 “DP 하나로 다 끝나고 dispatch만 하면 된다”기보다는,
dispatch가 먼저 후보 그룹을 만들고, 그 후보에 대해 packing/strategy 선택을 DP/ILP로 푼다는 구조에 더 가깝습니다.
즉 dispatch와 DP가 분리되지만 서로 강하게 연결되어 있습니다.

한 줄로 정리하면:

  • DP: micro-batch를 어떻게 자를지, 그리고 그 묶음이 어떤 strategy에서 얼마나 걸릴지 계산
  • dispatch: 어떤 sequence를 어떤 묶음에 넣을지 결정
  • parallelism: 각 묶음 내부를 실제로 돌릴 실행 전략 선택

그래서 당신이 말한 “DP로 balancing을 맞추고, dispatch만 잘하면 된다”는 건 절반은 맞고,
정확히는 dispatch가 만든 후보 위에서 DP가 balancing을 정교하게 하는 구조입니다.

You

1. 후보 그룹을 만들 떄 어떤 parallelism을 써야 될지 정해야하는거 아니야?

Assistant

맞습니다. 후보 그룹을 만들 때도 어떤 parallelism이 가능한지/유리한지 먼저 알아야 합니다.
왜냐하면 어떤 그룹이 feasible한지는 결국 그 그룹에 대해 쓸 수 있는 parallel strategy의 MaxLen(P)와 T(l,P)에 달려 있기 때문입니다.

다만 순서는 이렇게 보는 게 더 정확합니다.

  1. 먼저 각 parallel strategy를 profiling해서 비용표를 만든다.
  2. 그 비용표를 바탕으로 이 길이 구간은 어떤 strategy 후보들이 가능한지를 계산한다.
  3. 그다음 후보 그룹(예: ABC, ABD, CD)마다 가능한 strategy들 중 최저 비용을 붙여서 비교한다.

즉, 후보 그룹 생성과 parallelism 선택이 완전히 분리된 건 아니고, strategy feasibility를 보고 그룹을 평가합니다.
쉽게 말하면 “그룹을 먼저 눈대중으로 만들고 전략을 나중에 고른다”가 아니라,
그룹 후보를 평가할 때 strategy 제약을 같이 본다는 뜻입니다.

그래서 당신 말대로, 후보 그룹을 만들 때 parallelism을 고려해야 하는 건 맞습니다.
다만 논문식 표현에서는 그걸 “그룹을 만들 때 전략을 하나 정한다”기보다,
그룹마다 가능한 strategy 집합을 보고 비용을 계산한다고 이해하는 편이 정확합니다.

You

잠깐만 ABC/D 를 분리하는게 microbatch라고했잖아. 즉, ABC는 1 parallelism에 한번에 실행되어야 하는 pack이고 D는 또 홀로 실행되어야 하는 pack이라는거야? 아 그냥, sequence length 1, 30, 40, 80, 90 을 예시로 너가 DP를 채워서 이야기 해줘

Assistant

맞아요. ABC/D처럼 분리된 각 덩어리(=micro-batch)는 각각 하나의 실행 단위로 보면 됩니다.
다만 그 덩어리 안의 sequence들이 같은 parallelism strategy로 함께 처리되는 패킹 결과라고 이해하면 정확합니다.

예시로 sequence length가 1, 30, 40, 80, 90이고,
가능한 strategy가 아주 단순하게 2개라고 해볼게요.

  • S1: 짧은 sequence에 빠름, MaxLen(S1)=40
  • S2: 긴 sequence까지 가능, MaxLen(S2)=100

profiling cost를 임의로 이렇게 두겠습니다.

  • 단일 sequence 비용

    • T(1,S1)=1, T(30,S1)=1.2, T(40,S1)=1.4
    • T(1,S2)=1.5, T(30,S2)=1.7, T(40,S2)=1.9, T(80,S2)=2.6, T(90,S2)=2.8
  • packing된 micro-batch 비용은 “묶었을 때의 총 길이/최장길이”에 따라 더 작아진다고 가정하겠습니다.


1) 후보 micro-batch를 어떻게 보나

연속된 sequence만 묶는다고 해보면 가능한 partition은 예를 들어:

  • [1] [30] [40] [80] [90]
  • [1,30] [40] [80] [90]
  • [1,30,40] [80] [90]
  • [1,30,40,80] [90]
  • [1,30] [40,80] [90]
  • 이런 식입니다.

Hydraulis는 이 후보들에 대해 각 묶음이 어떤 strategy에서 가능한지 보고,
그중 비용이 최소가 되도록 DP를 합니다.


2) DP 상태

dp[i] = 첫 i개 sequence를 최적으로 packing했을 때의 최소 비용

즉:

  • dp[1]: [1]까지 최적
  • dp[2]: [1,30]까지 최적
  • ...
  • dp[5]: [1,30,40,80,90]까지 최적

점화식은:

dp[i] = min over j<i { dp[j] + cost(j+1 .. i) }

여기서 cost(j+1..i)는
sequence j+1 ~ i를 하나의 micro-batch로 묶었을 때의 최소 비용입니다.
그리고 그 최소 비용은 가능한 strategy들 중 가장 싼 걸 고릅니다.


3) 실제로 채워보기

dp[1]

  • [1]
  • S1 가능, S2 가능
  • 더 싼 건 S1이라고 합시다.
  • dp[1] = 1

dp[2]

  • 후보:
    1. [1] + [30] = dp[1] + cost([30])
    2. [1,30]

가정상:

  • [30] 단독은 S1 가능, 비용 1.2
  • [1,30]을 묶으면 S1에서 1.4, S2에서 1.6이라고 합시다.

그러면:

  • 따로: 1 + 1.2 = 2.2
  • 묶기: 1.4

→ dp[2] = 1.4 with [1,30]


dp[3] = [1,30,40]

후보:

  1. dp[2] + cost([40]) = 1.4 + 1.4 = 2.8
  2. dp[1] + cost([30,40])
  3. cost([1,30,40])

가정상:

  • [30,40] 묶기 비용 = 1.8
  • [1,30,40] 묶기 비용 = 2.0

그러면:

  • 1.4 + 1.4 = 2.8
  • 1 + 1.8 = 2.8
  • 2.0

→ dp[3] = 2.0 with [1,30,40]

즉 첫 3개는 한 micro-batch로 묶는 게 좋다고 선택.


dp[4] = [1,30,40,80]

후보:

  1. dp[3] + cost([80]) = 2.0 + 2.6 = 4.6
  2. dp[2] + cost([40,80])
  3. dp[1] + cost([30,40,80])
  4. cost([1,30,40,80])

가정상:

  • [40,80]은 S2만 가능, 비용 3.0
  • [30,40,80]은 S2만 가능, 비용 3.2
  • [1,30,40,80]은 S2만 가능, 비용 3.4

그러면:

  • 4.6
  • 1.4 + 3.0 = 4.4
  • 1 + 3.2 = 4.2
  • 3.4

→ dp[4] = 3.4 with [1,30,40,80]


dp[5] = [1,30,40,80,90]

후보:

  1. dp[4] + cost([90]) = 3.4 + 2.8 = 6.2
  2. dp[3] + cost([80,90])
  3. dp[2] + cost([40,80,90])
  4. dp[1] + cost([30,40,80,90])
  5. cost([1,30,40,80,90])

가정상:

  • [80,90] 비용 = 3.6
  • [40,80,90] 비용 = 3.8
  • [30,40,80,90] 비용 = 4.0
  • 전체 묶음 비용 = 3.9

그러면:

  • 6.2
  • 2.0 + 3.6 = 5.6
  • 1.4 + 3.8 = 5.2
  • 1 + 4.0 = 5.0
  • 3.9

→ dp[5] = 3.9 with [1,30,40,80,90]


4) 이 예시가 말하는 것

이 예시에서는 우연히 다 묶는 게 제일 싸다고 나왔지만,
숫자를 바꾸면 당연히 중간에서 끊는 게 더 좋을 수 있습니다.

중요한 건 Hydraulis의 DP가:

  • sequence들을 어떤 micro-batch로 나눌지
  • 그 micro-batch가 어떤 strategy에서 실행될지 를 prefix 최적해 재사용 방식으로 찾는다는 점입니다.

5) 당신 질문에 대한 직접 답

ABC/D를 분리하는게 microbatch라고 했잖아. 즉, ABC는 1 parallelism에 한번에 실행되어야 하는 pack이고 D는 또 홀로 실행되어야 하는 pack이라는거야?

네, 그렇게 이해하면 됩니다.
정확히는 ABC가 하나의 micro-batch pack이고, D가 또 다른 pack입니다.
그리고 각 pack은 그 pack에 맞는 parallelism strategy로 실행됩니다.


원하시면 다음 답변에서 제가 이 예시를 “어떤 구간에서 끊는지”가 더 분명하게 보이도록 진짜 DP 표 형태로 다시 써드릴게요.

You

아 이해했어. LNK로 넘어가자. LNK 구현 어떻게 했는지, parallelism 바꾸는 plan은 어떻게 하는지 등에 대한 이야기가 있어? weight movement에 대한 의문이야.

Assistant

있습니다. 다만 제가 지금까지 설명한 흐름에서 핵심은 LNK가 “parallelism을 바꿀 때 필요한 weight/gradient 재배치 연산자”라는 점이에요.
즉, LNK는 단순한 통신 primitive가 아니라 현재 strategy의 shard layout과 다음 strategy의 shard layout을 맞추는 resharding 메커니즘입니다.

1) LNK가 하는 일

Hydraulis에서 propagation 쪽 parallelism이 바뀌면, weight가 지금 가진 shard 방식과 다음 step에서 필요한 shard 방식이 달라집니다.
이때 LNK가:

  • parameter를 필요한 granularity로 쪼개고
  • 다른 rank로 send/receive 하거나
  • 로컬에서 rearrange 해서
  • 다음 parallelism이 바로 쓸 수 있게 만듭니다.

즉, “weight movement”는 전략 전환 시 발생하는 shard-to-shard 이동입니다.


2) 논문이 말하는 구조

논문은 이걸 보통:

  • pull: optimization state에서 propagation용 parameter view를 가져옴
  • push: backward 후 gradient를 optimization state로 되돌림
  • LNK: 이 둘 사이에서 필요한 reshard / communication을 수행

으로 봅니다.

LNK의 세부 동작은 보통:

  • 서로 다른 tensor partition 간의 대응 관계를 계산하고
  • 그 대응에 맞게 조각을 이동시키는 방식입니다.

3) parallelism 바꾸는 plan은 어떻게 하냐

전략 변경은 iteration 단위 planning으로 다룹니다.
즉, 매 token마다 바꾸는 게 아니라:

  1. 이번 iteration의 sequence 분포를 보고
  2. candidate strategy를 고르고
  3. 그 전략 조합에 맞는 dispatch를 정하고
  4. 실행 중 필요한 지점에서 LNK를 통해 reshard합니다.

즉, plan은 미리 정하고, LNK는 그 plan을 실행하는 operator에 가깝습니다.


4) weight movement에 대한 핵심 의문

사용자님 의문은 사실 이거죠:

“strategy가 바뀔 때마다 weight를 계속 옮기면 너무 비싸지 않나?”

맞습니다. 그래서 Hydraulis는

  • strategy를 너무 자주 바꾸지 않도록 candidate를 줄이고
  • 통신을 subgraph로 묶어
  • computation과 overlap시키는 방향으로 설계합니다.

즉, weight movement는 존재하지만, 최소화되도록 계획되고, 남는 비용은 overlap으로 숨기려는 구조예요.


5) 한 줄 요약

  • LNK = 서로 다른 parallelism의 shard layout을 맞추는 resharding/communication 연산
  • plan = iteration 단위로 strategy/dispatch를 미리 정하는 것
  • weight movement = 그 plan에 따라 필요한 시점에만 발생하도록 설계된 shard 이동

원하시면 다음 답변에서 제가
“TP8 → TP4+PP2로 바뀔 때 parameter shard가 어떻게 이동하는지”를 간단한 그림처럼 설명해드릴게요.

You

1. PP 는 어떻게 활용해? 2. 가장 중요한거는, training에는 너무 다양한 데이터들이 많아. 1. AC를 어떻게 할건지, PP를 한다면 balancing, micro pp batch를 어떻게 packing을 할건지, 2. 이 데이터를 다른 non-PP 와 어떻게 비교할건지, 등에 대한 일들이 계속 발생해. 이것에 대해서 다루는게 있어?

Assistant
  1. PP는 stage를 나누는 데 활용됩니다.
    Hydraulis에서 PP는 각 pipeline/strategy가 한 덩어리의 모델을 여러 stage로 나눠서 처리할 때 쓰이고, sequence length가 긴 경우에 메모리/계산 부담을 stage로 분산시키는 역할을 합니다.
    즉, PP는 단순히 “더 많은 단계”가 아니라 긴 sequence나 메모리-heavy한 strategy를 감당하기 위한 수단입니다.

  2. 네, 당신이 말한 문제를 논문이 핵심 문제로 봅니다.
    특히:

    • 어떤 데이터는 AC처럼 묶는 게 좋고,
    • 어떤 데이터는 PP를 써서 stage balancing을 해야 하고,
    • 어떤 데이터는 non-PP가 더 낫고,
    • 그래서 데이터마다 최적 parallelism과 packing이 달라진다 는 점이 논문의 출발점입니다.

    Hydraulis는 이걸 data distribution-aware strategy proposal + two-stage sequence assignment으로 다루려고 합니다.
    먼저 데이터 길이 분포를 보고 가능한 strategy 후보들을 추리고,
    그다음 pipeline 간 dispatch와 pipeline 내부 packing으로 각 데이터 묶음에 맞는 실행 방식을 정합니다.
    즉, “AC를 어떻게 할지”, “PP에서 stage를 어떻게 balance할지”, “PP/non-PP를 어떻게 비교할지”를 길이 분포와 cost model 기반으로 자동 결정하려는 겁니다.

    다만 중요한 한계도 있습니다.
    이 논문이 모든 데이터 유형/모든 token 패턴에 대해 완전한 일반해를 주는 건 아니고,
    length distribution 중심으로 문제를 모델링합니다.
    그래서 당신이 말한 “training 중 계속 생기는 다양한 데이터 패턴들”을 전부 세밀하게 다루기보다는,
    길이-기반 비용 모델로 충분히 잘 근사되는 범위를 노립니다.

원하면 다음 답변에서 제가
“PP vs non-PP를 Hydraulis가 길이 분포 기준으로 어떻게 비교하는지”를 예시로 풀어드릴게요.

You

1. stage라는 개념은 어디서 갑자기 튀어나왔지?

Assistant

stage는 pipeline parallelism의 구성 단위라서 튀어나온 게 아니라, PP를 말하는 순간 자연스럽게 따라오는 개념입니다.
즉, 모델 전체를 여러 조각으로 나눴을 때 그 조각 하나하나가 stage예요.
예를 들어 4-stage PP면, forward/backward가 stage 1 → 2 → 3 → 4 순서로 흘러갑니다.
Hydraulis에서 PP를 활용한다는 말은, 긴 sequence나 큰 모델을 이런 stage 단위로 나눠서 처리한다는 뜻입니다.
반면 TP는 한 stage 내부에서 텐서를 쪼개는 방식이고, CP는 context 차원 분산에 가깝습니다.
그래서 제가 stage를 언급한 건, PP를 설명하면 필연적으로 필요한 용어라서였습니다.
다만 Hydraulis의 핵심 관심은 stage 자체보다, sequence 길이에 따라 어떤 TP/PP/CP 조합이 유리한지를 고르는 것입니다.
즉 stage는 PP의 표현이고, 논문의 핵심은 stage 배치 그 자체보다 heterogeneous strategy 선택과 packing입니다.

You

아 그건 알겠어. 내 말은 PP Stage를 나누는데 사용됩니다가 아니라, PP는 복잡성이 있는데 이거로 최적화 하냐는걸 물어보는거였어.

Assistant

아, 네. 그 질문이면 답은 이겁니다: 네, Hydraulis는 PP를 “그냥 쓰는” 게 아니라, PP가 만드는 복잡성까지 최적화 변수로 봅니다.

구체적으로는:

  1. PP stage 수가 달라지면 각 stage의 계산량, activation 전달량, bubble이 달라집니다.
  2. Hydraulis는 이 차이를 T(l, P) 같은 profiling 비용에 반영해서, 어떤 strategy가 이 길이에서 더 싼지 비교합니다.
  3. packing 단계에서는 micro-batch들을 stage별로 균형 있게 묶어서, 특정 stage만 너무 길어지지 않게 합니다.
  4. 그래서 PP는 단순히 “메모리 아끼는 옵션”이 아니라, strategy 후보의 비용을 바꾸는 요소로 들어갑니다.

즉, PP의 복잡성 자체를 정교하게 모델링한다기보다,
PP가 포함된 strategy의 실행 비용을 실측/프로파일링 기반으로 반영해서 최적화하는 방식입니다.
그래서 “PP stage를 어떻게 나눌지”를 이론적으로 새로 푸는 것보다는,
PP가 들어간 strategy들 사이를 비용 비교해서 고르는 최적화에 가깝습니다.

한 줄로 말하면:
Hydraulis는 PP를 직접 설계하는 논문이라기보다, PP를 포함한 heterogeneous parallel strategy를 비용 모델로 최적화하는 논문입니다.

You

PP에 대한 policy는 어떻게 가져가? 이거도 얘기해볼 수 있을까? 그리고 이전에 pp 최적화 논문이 무수히 많았잖아.

Assistant

네, 이건 중요합니다. Hydraulis는 PP policy를 새로 발명하는 논문이라기보다, 기존 PP가 이미 있거나 가능하다는 전제 위에서 그 PP를 포함한 전체 strategy를 고르는 쪽에 가깝습니다.
즉, “PP stage를 어떻게 설계할까”를 정면으로 푸는 게 아니라, PP가 들어간 candidate strategy들의 성능을 비교해 선택합니다.

그래서 PP policy는 대략 이렇게 이해하면 됩니다:

  1. 모델을 몇 stage로 나눌지,
  2. 각 stage에 어떤 layer를 넣을지,
  3. bubble과 activation communication 비용이 어느 정도인지
    를 profiled cost로 반영합니다.

Hydraulis의 핵심은 그 위에:

  • 길이 분포에 따라
  • TP/PP/CP 조합이 다른 strategy들을 비교하고
  • packing/dispatch까지 같이 최적화한다는 점입니다.

즉, 기존의 PP 최적화 논문들이 주로 다룬 것은:

  • stage partitioning
  • bubble 최소화
  • load balance
  • activation checkpointing 같은 PP 내부 문제였고,

Hydraulis는 그보다 바깥에서:

  • variable-length data
  • heterogeneous strategy
  • dispatch/packing
  • shard resharding(LNK) 를 함께 최적화합니다.

그래서 관계를 정리하면:

  • 기존 PP 논문: PP 자체를 더 잘 만드는 문제
  • Hydraulis: PP를 포함한 전체 training strategy를 데이터 길이 분포까지 고려해 고르는 문제

원하면 다음 답변에서 제가
“Hydraulis가 PP policy를 직접 최적화하지 않는 이유”를 기존 PP 논문과 비교해서 더 선명하게 정리해드릴게요.

You

그래 대충 이해했어. 내 생각에 understanding.md 를 수정을 해야할 때라고 생각해서. 1. parameter pull push 와 같은 자체적인 용어를 전부 정리해줬으면 좋겠어. 기존 legacy 용어와 맞는 contract로 수정하자. 내가 느낀건, LNK가 P1 -> P2 로 조절할 때 parameter movement를 일종의 compilation을 하는 것처럼 느꼈어. p2p operation들로 묶는데, 그 p2p operation들을 nccl all to all primitive 로 전환할 수 있다면 전환한다. 라는 것처럼 보여서. 거기에 추가적으로 gradient가 발생하면 gradient를 shard optimizer의 좌표를 찍어서 p2p로 보내는 그런 것들을 생각했어. 이게 맞는거지? 두번째로, 여기서 parallelism -> parallelism 으로 이동할 때 bubble이 발생할 수 있다는 걸 생각을 하고 있는건지가 궁금해서. 예를들어서 CP1 + CP1 으로 2gPU 를 돌리다가 CP2 로 넘어가려고 하면은 이 부분에 대해서 잘 처리를 하고 있는 상황이야? CP1과 또 다른 CP1이 latency가 다를 수 밖에 없기 때문에 bubble이 생길 수 밖에 없거든.

source artifactrejected

Clarify LNK, pull/push, and bubble handling in understanding.md

Patch the source understanding to align terminology with legacy distributed-training concepts and clarify what LNK does during parallelism transitions, including whether bubble effects are modeled.

sources/8401deff26ff/understanding.md