Chuyên gia bị bỏ đói
Chuyên gia bị bỏ đói
Bộ định tuyến không được ai bảo phải chia đều. Nó học cách chọn, và cái nó học được thường là dồn phần lớn token vào vài chuyên gia, để số còn lại nằm im mà bạn vẫn trả tiền bộ nhớ cho chúng.
Ở bài định tuyến và tham số hoạt động bạn đã thấy lời hứa của trộn chuyên gia: giữ rất nhiều tham số trong bộ nhớ nhưng mỗi token chỉ chạy qua một phần nhỏ. Bài này hỏi câu tiếp theo, và là câu thực tế nhất: phần nhỏ đó có được chia đều không.
Câu trả lời mặc định là không. Bộ định tuyến chỉ là một ma trận được huấn luyện cùng phần còn lại, và không có gì trong hàm mất mát bảo nó phải công bằng. Một chuyên gia được chọn nhiều thì học nhanh hơn, học nhanh hơn thì lại được chọn nhiều hơn, vòng lặp đó tự khoá lại. Kết quả là một lô token có thể dồn hết vào vài chuyên gia trong khi hàng trăm chuyên gia khác không nhận được token nào, tức bạn đang trả bộ nhớ cho tham số không làm gì, và nếu mỗi chuyên gia nằm trên một thiết bị thì cả lô phải ngồi chờ đúng thiết bị đông nhất. Sim dưới đây đo cả ba chuyện đó, rồi cài cả hai cách chữa để bạn so trên cùng một lô.
1 · Một lô token đi qua bộ định tuyến ✎ sửa được
Phần cứng bỏ không tính thẳng từ hệ số mất cân bằng: 1 - 1/3.00 = 66.7%. Lý do là cả lô phải chờ chuyên gia đông nhất, nên thời gian tường là 8 × 24 đơn vị thiết bị, trong khi việc thật sự làm chỉ có 64 lượt.
2 · Cách chữa thứ nhất: hàm mất mát phụ trợ ✎ sửa được
Giá trị của nó là hệ số × 8 × tổng theo chuyên gia của (tỉ lệ token × tỉ lệ điểm cổng). Ở lô này phần trong ngoặc cho 0.16988, nhân 8 ra 1.3591, nhân hệ số 0.01 ra 0.01359. Khi tải hoàn toàn đều thì cả hai tỉ lệ đều bằng 1/8, nên phần sau hệ số về đúng 1: đó là sàn của con số này, kéo độ lệch về 0 mà xem.
| chuyên gia | tải | tỉ lệ token | tỉ lệ điểm cổng | tích |
|---|---|---|---|---|
| 0 | 24 | 37.50% | 19.01% | 0.07130 |
| 1 | 20 | 31.25% | 17.49% | 0.05467 |
| 2 | 8 | 12.50% | 15.69% | 0.01961 |
| 3 | 8 | 12.50% | 13.67% | 0.01708 |
| 4 | 4 | 6.25% | 11.54% | 0.00721 |
| 5 | 0 | 0.00% | 9.43% | 0.00000 |
| 6 | 0 | 0.00% | 7.46% | 0.00000 |
| 7 | 0 | 0.00% | 5.71% | 0.00000 |
3 · Cách chữa thứ hai: điều chỉnh bias, không cần mất mát phụ trợ ✎ sửa được
0.05 và nâng bias của chuyên gia đói lên đúng chừng đó. Hệ số mất cân bằng đi từ 3.00× xuống 3.00×.| chuyên gia | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| bias | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
| tải | 24 | 20 | 8 | 8 | 4 | 0 | 0 | 0 |
- 0 token đã đổi chuyên gia, và 32 token giữ nguyên. Bias rõ ràng có tác dụng lên việc chọn ai.
- Trên những token giữ nguyên tập chuyên gia, trọng số trộn lệch nhiều nhất 0, và điểm cổng của người thắng lệch 0. Không phải xấp xỉ nhỏ, mà là đúng bằng không.
- Lý do rất cơ học: bias chỉ cộng vào điểm để xếp hạng. Trọng số trộn lấy từ điểm cổng gốc chia cho tổng điểm cổng của những người thắng, và trong phép chia đó không có mặt bias.
topk_method: noaux_tc trong tệp cấu hình của DeepSeek-V3: cân bằng được tải mà không phải bơm thêm một số hạng nào vào gradient.4 · Giới hạn định tuyến theo nhóm ✎ sửa được
n_group và topk_group tạm ẩn khi giới hạn đang tắt, vì lúc đó chúng không đổi được con số nào. Bật công tắc để chúng hiện lại.Đang tắt, nên mỗi token được chọn trong cả 8 chuyên gia. Bật lên để thấy tập lựa chọn bị thu lại. DeepSeek-V3 đặt n_group bằng 8 và topk_group bằng 4, tức token chỉ được chọn trong 4 trên 8 nhóm.
5 · Bộ nhớ bạn trả cho chuyên gia không làm gì ✎ sửa được
Một chuyên gia kiểu feed-forward có cổng gồm ba ma trận, nên nó nặng 3 × 4.096 × 14.336 = 176.16 triệu tham số. Cả 8 chuyên gia của một lớp là 1.41 tỉ tham số, tức 2.63 GiB. Mỗi token chỉ chạy qua 2 trong số đó, tức 352.32 triệu tham số hoạt động.
6 · Từng token đi đâu
| token | chuyên gia được chọn | điểm cổng | bias | điểm để xếp hạng | trọng số trộn | × hệ số nhân 1 |
|---|---|---|---|---|---|---|
| 0 | 0, 1 | 0.953 · 0.900 | 0.00 · 0.00 | 0.953 · 0.900 | 0.514 · 0.486 | 0.514 · 0.486 |
| 1 | 1, 2 | 0.929 · 0.854 | 0.00 · 0.00 | 0.929 · 0.854 | 0.521 · 0.479 | 0.521 · 0.479 |
| 2 | 2, 3 | 0.895 · 0.792 | 0.00 · 0.00 | 0.895 · 0.792 | 0.530 · 0.470 | 0.530 · 0.470 |
| 3 | 3, 0 | 0.847 · 0.755 | 0.00 · 0.00 | 0.847 · 0.755 | 0.529 · 0.471 | 0.529 · 0.471 |
| 4 | 0, 4 | 0.818 · 0.783 | 0.00 · 0.00 | 0.818 · 0.783 | 0.511 · 0.489 | 0.511 · 0.489 |
| 5 | 0, 1 | 0.867 · 0.745 | 0.00 · 0.00 | 0.867 · 0.745 | 0.538 · 0.462 | 0.538 · 0.462 |
| 6 | 0, 1 | 0.905 · 0.809 | 0.00 · 0.00 | 0.905 · 0.809 | 0.528 · 0.472 | 0.528 · 0.472 |
| 7 | 0, 1 | 0.932 · 0.861 | 0.00 · 0.00 | 0.932 · 0.861 | 0.520 · 0.480 | 0.520 · 0.480 |
| 8 | 0, 1 | 0.953 · 0.900 | 0.00 · 0.00 | 0.953 · 0.900 | 0.514 · 0.486 | 0.514 · 0.486 |
| 9 | 1, 2 | 0.929 · 0.854 | 0.00 · 0.00 | 0.929 · 0.854 | 0.521 · 0.479 | 0.521 · 0.479 |
routed_scaling_factor: nó áp sau khi các chuyên gia đã chạy xong nên không đụng gì tới việc chọn, và tổng mỗi hàng bằng đúng 1 chứ không phải 1.- Điểm cổng ở đây do tôi sinh ra bằng một công thức tất định, trộn giữa một thành phần xoay vòng và một thành phần thiên vị chuyên gia đầu bảng, rồi đưa qua sigmoid. Mô hình thật học ma trận cổng trên dữ liệu. Nên mức mất cân bằng của mô hình thật không suy ra được từ đây, và núm độ lệch không phải tham số của mô hình nào cả.
- Cái sim làm đúng là cơ chế của hai cách chữa và phần số học của tải. Nó không cho thấy chất lượng mô hình đổi thế nào khi bạn thêm mất mát phụ trợ hay bỏ nó đi. Phần đó phải huấn luyện mới biết.
- Quỹ đạo bias ở đây đã được làm cho dễ đọc. Luật gốc là cộng trừ theo dấu, và vì top-k là phép chọn rời rạc nên nó vọt quá rồi dao động: trên một lưới 1920 cấu hình tôi đo được 760 cấu hình có bước làm hệ số xấu đi. Sim vì vậy chỉ nhận một bước khi bước đó không làm hệ số tệ hơn, nếu không thì chia đôi bước và thử lại tối đa ba lần. Huấn luyện thật không làm vậy và cũng không cần: mỗi lô là một lô khác nên dao động bị trung bình hoá.
- Hệ số mất cân bằng và tỉ lệ phần cứng bỏ không đều là thước đo của một lô. Hệ thống thật còn có sức chứa của chuyên gia, còn thả token khi tràn, còn xếp lô lại với nhau, nên số thực tế khác con số ở đây.
- Preset mang tên mô hình chỉ chép lại tham số công bố kèm nguồn và ngày. Cổng kiểm số canh phép tính, không canh chuyện mô hình ngoài kia có đúng cấu hình đó hay không.
Đọc ba con số đầu tiên
Ở trạng thái mở bài, lô có 32 token, 8 chuyên gia, mỗi token chọn 2, và núm độ lệch đặt ở 50. Tải ra là 24, 20, 8, 8, 4, 0, 0, 0.
Bất biến mạnh nhất của cả bài là phép cộng đơn giản nhất. Cộng dãy trên được 64, đúng bằng 32 token × 2 chuyên gia mỗi token. Con số đó không đổi dù bạn kéo độ lệch đi đâu, bật giới hạn theo nhóm hay chạy bao nhiêu bước sửa bias: mỗi token phát đúng k phiếu, nên tổng phiếu là hằng số. Cái đổi chỉ là chúng rơi vào ai. Cổng kiểm số của bài này khẳng định đẳng thức đó trên vài nghìn cấu hình, kể cả các cấu hình biên như lô rỗng hay k = 0.
Hệ số mất cân bằng là tải lớn nhất chia tải trung bình. Trung bình là 64 / 8 = 8, lớn nhất là 24, nên hệ số bằng 24 / 8 = 3,00. Cách đọc: chuyên gia đông nhất đang gánh gấp ba lần phần đáng ra của nó. Con số này có hai mốc đóng rất tiện để tự kiểm. Kéo độ lệch về 0 thì mọi chuyên gia nhận đúng 8 token và hệ số về đúng 1, không phải xấp xỉ 1. Đổi sang preset "Dồn cục tối đa" (độ lệch 100, mỗi token chọn 1) thì cả 32 token dồn vào chuyên gia 0, trung bình là 32 / 8 = 4, nên hệ số bằng 32 / 4 = 8, đúng bằng số chuyên gia. Đó là trần của thước đo này khi k = 1.
Tỉ lệ phần cứng bỏ không suy thẳng ra từ hệ số. Giả sử mỗi chuyên gia nằm trên một thiết bị riêng và cả lô phải chờ thiết bị chậm nhất. Thời gian tường tỉ lệ với tải lớn nhất, nên tổng công suất bỏ ra là 8 thiết bị × 24 token = 192 đơn vị, trong khi việc thật sự làm chỉ có 64 lượt. Bỏ không 1 - 64/192 = 66,7%, và viết gọn lại thì luôn đúng 1 - 1/hệ số. Ở mốc cân bằng hoàn hảo, hệ số bằng 1 nên bỏ không bằng 0. Ở mốc dồn cục với 8 chuyên gia, hệ số bằng 8 nên bỏ không 1 - 1/8 = 87,5%.
Còn con số làm người ta chịu chi tiền để sửa chuyện này nằm ở mục 5. Với kích thước chuyên gia của Mixtral, mỗi chuyên gia nặng 3 × 4096 × 14336 bằng 176,16 triệu tham số, cả 8 chuyên gia của một lớp là 1,41 tỉ tham số tức 2,63 GiB ở 2 byte. Ba chuyên gia đói trong lô này ứng với 1008,0 MiB nằm im, tức 37,5% bộ nhớ chuyên gia của lớp đó. Bấm sang preset DeepSeek-V3 thì tỉ lệ còn khó nhìn hơn: 146 trên 256 chuyên gia không nhận token nào, tức 5,99 GiB trên 10,5 GiB.
Cách chữa thứ nhất: thêm một số hạng vào hàm mất mát
Cách cổ điển là bịa ra một số hạng phạt sự mất cân bằng rồi cộng nó vào hàm mất mát khi huấn luyện. Dạng hay gặp nhất tính theo tích của hai phân bố trên tập chuyên gia:
- tỉ lệ token: mỗi chuyên gia nhận bao nhiêu phần trong tổng số lượt gán, tức
tải / (số token × k); - tỉ lệ điểm cổng: điểm cổng trung bình mà bộ định tuyến dành cho chuyên gia đó, chuẩn hoá trên toàn bộ chuyên gia.
Giá trị là hệ số × số chuyên gia × tổng theo chuyên gia của tích hai tỉ lệ. Bảng trong mục 2 in ra từng cột để bạn nhân tay lại được. Ở trạng thái mở bài, phần sau hệ số cho 1,3591, nhân hệ số 0,01 ra 0,01359. Kéo độ lệch về 0 thì cả hai tỉ lệ đều bằng 1/8, nên phần sau hệ số về đúng 8 × 8 × (1/8) × (1/8) = 1. Đó là sàn của con số này, và bạn kiểm được bằng tay trong ba dòng.
Vì sao nó có tác dụng: tỉ lệ token là phép đếm, không khả vi, còn tỉ lệ điểm cổng thì khả vi. Nhân hai thứ vào nhau rồi cho vào hàm mất mát thì gradient chảy qua vế điểm cổng, và nó kéo ma trận cổng theo hướng hạ điểm của chuyên gia đang quá tải. Nói cách khác, cách này can thiệp trực tiếp vào gradient. Đây là chỗ phải nói thẳng cái giá: bạn đang bắt mô hình đánh đổi một phần khả năng chọn đúng chuyên gia để lấy cân bằng tải. Hệ số càng lớn thì cân bằng càng nhanh mà can thiệp càng nặng, và sim này không đo được phần chất lượng bị đổi đi, nó chỉ cho bạn thấy giá trị của số hạng phạt đổi ra sao.
Cách chữa thứ hai: một số bias, chỉ để chọn
Cách thứ hai bỏ hẳn số hạng phạt. Mỗi chuyên gia được gắn thêm một số b, và số đó chỉ cộng vào điểm dùng để xếp hạng, không nhân vào trọng số đầu ra. Sau mỗi lô, chuyên gia nào quá tải thì hạ b của nó xuống, chuyên gia nào đói thì nâng lên. Trong tệp cấu hình công bố của DeepSeek-V3, đây chính là trường topk_method mang giá trị noaux_tc, tức "top-k không dùng mất mát phụ trợ".
Bấm nút "+1 bước" trong mục 3 rồi nhìn cột hệ số. Ở trạng thái mở bài nó đi 3,00 · 2,50 · 2,00 · 2,00 · 1,50 rồi giữ ở 1,50 vài bước trước khi xuống 1,00 ở bước thứ 9, và từ đó tải là 8, 8, 8, 8, 8, 8, 8, 8 phẳng lì. Bảng bias ngay dưới cho thấy vì sao: bias của chuyên gia 0 đã bị kéo xuống -0,20 còn bias của chuyên gia 7 được nâng lên +0,30.
Nhưng điểm sư phạm quan trọng nhất không nằm ở đường đi xuống đó, mà ở khung có viền ngay sau nó. Sau 12 bước, sim đối chiếu lô lúc bias bằng 0 với lô lúc này và báo ba con số:
- 24 token đã đổi chuyên gia, 8 token giữ nguyên. Bias rõ ràng có tác dụng lên chuyện ai được chọn.
- Trên những token giữ nguyên tập chuyên gia, trọng số trộn lệch đúng 0, và điểm cổng của người thắng cũng lệch đúng 0. Không phải "nhỏ tới mức bỏ qua được", mà là bằng không.
- Lý do rất cơ học, và bạn đối chiếu được ngay trong bảng token ở mục 6: cột điểm để xếp hạng đúng bằng cột điểm cổng cộng bias, còn cột trọng số trộn chỉ lấy điểm cổng gốc chia cho tổng điểm cổng gốc của nhóm thắng. Trong phép chia đó không có mặt bias.
Đó là toàn bộ mẹo: cân bằng được tải mà không phải bơm thêm số hạng nào vào gradient, nên không phải đánh đổi chất lượng theo kiểu của cách thứ nhất. Cổng kiểm số khoá đúng khẳng định này bằng một đột biến: nếu ai đó sửa engine để trọng số trộn tính từ điểm đã cộng bias, cổng đỏ ngay.
Và cũng phải nói luôn chỗ cách thứ hai không làm được gì. Mở preset "Dồn cục tối đa" rồi chạy hết 12 bước: hệ số vẫn đúng 8,00 và tổng cải thiện đúng bằng 0. Với k = 1 và mọi token có cùng thứ hạng chuyên gia, cộng chung một vector bias vào thì thứ hạng vẫn giống hệt nhau ở mọi token, nên cả lô vẫn dồn vào đúng một người. Bias chỉ dời được đống token sang chuyên gia khác, chứ không chia nhỏ nó ra. Cách chữa này cần token khác nhau mới có chỗ bám.
Chi tiết thật nữa: định tuyến bị giới hạn theo nhóm
DeepSeek-V3 còn cắt thêm một lớp mà lý do không phải cân bằng. Trong cấu hình có n_group bằng 8 và topk_group bằng 4: 256 chuyên gia được chia thành 8 nhóm, mỗi nhóm được chấm bằng tổng hai điểm cổng cao nhất trong nhóm, và mỗi token chỉ được chọn trong 4 nhóm tốt nhất. Mục đích là giảm lưu lượng mạng giữa các máy: nếu mỗi nhóm nằm trên một máy thì một token chỉ phải đi tới 4 máy thay vì rải khắp 8.
Sim cài đủ phần này, bạn bật công tắc ở mục 4 là thấy ô "chuyên gia mà một token còn với tới được" tụt xuống. Ở trạng thái mở bài, 8 chuyên gia chia 4 nhóm và giữ 2 nhóm, tức chỉ còn 4 trên 8 chuyên gia trong tầm với, và tải đổi từ 24, 20, 8, 8, 4, 0, 0, 0 sang 24, 20, 8, 4, 8, 0, 0, 0. Hãy để ý điều này: hệ số mất cân bằng gần như không nhúc nhích. Đúng như kỳ vọng, vì giới hạn theo nhóm không phải một cách cân bằng tải, nó là một cách tiết kiệm mạng. Trộn lẫn hai mục đích đó là hiểu sai cấu hình.
Đọc preset cho đúng, và ranh giới của sim
Hai preset mang tên mô hình chỉ chép lại tham số công bố kèm nguồn và ngày. Preset "Cân bằng hoàn hảo" và "Dồn cục tối đa" là hai cực trị do tôi đặt ra để khoá hai đầu thước đo, và source line của chúng nói rõ là không có tham số mô hình nào ở đó. Preset thứ năm ghi rõ là số minh hoạ cho một lớp kích thước, không phải cấu hình của mô hình nào.
Điểm cổng ở đây do tôi sinh ra bằng một công thức tất định, trộn giữa một thành phần xoay vòng theo vị trí token và một thành phần thiên vị các chuyên gia đầu bảng, rồi đưa qua sigmoid. Không có Math.random ở đâu cả, và núm "độ lệch của định tuyến" là núm của tôi, không phải tham số của mô hình nào.
Mô hình thật thì học ma trận cổng trên dữ liệu. Nên mức mất cân bằng của một mô hình thật không suy ra được từ sim này. Cái sim làm đúng là cơ chế của hai cách chữa và phần số học của tải: nếu tải là như vậy thì hệ số, số chuyên gia đói và tỉ lệ phần cứng bỏ không phải là như vậy. Nó không cho thấy chất lượng mô hình đổi thế nào khi bạn thêm mất mát phụ trợ hay bỏ nó đi.
Thêm một chỗ sim khác thực tế, và tôi đo được nên nói ra: quỹ đạo bias đã được làm cho dễ đọc. Luật gốc là cộng trừ theo dấu, và vì top-k là phép chọn rời rạc nên một cú đẩy nhỏ có thể lật cả một khối token cùng lúc, khiến hệ số vọt quá rồi dao động quanh điểm cân bằng. Trên một lưới 1920 cấu hình tôi đo được 760 cấu hình có ít nhất một bước làm hệ số xấu đi. Sim vì vậy chỉ nhận một bước khi bước đó không làm hệ số tệ hơn, nếu không thì chia đôi bước và thử lại, tối đa ba lần. Huấn luyện thật không làm vậy và cũng không cần, vì mỗi lô là một lô khác nên dao động bị trung bình hoá. Khi không bước nào cải thiện được nữa, sim ghi thẳng "không cải thiện thêm" thay vì vẽ tiếp một đường đi xuống giả.
Cuối cùng, hệ số mất cân bằng và tỉ lệ phần cứng bỏ không đều là thước đo của một lô. Hệ thống thật còn có sức chứa cho mỗi chuyên gia, còn thả bớt token khi tràn, còn xếp nhiều lô lại với nhau, nên con số vận hành thật khác con số ở đây.
Định tuyến học được không tự cân bằng, và cái giá của mất cân bằng đo được chính xác bằng ba con số: tải lớn nhất chia tải trung bình, số chuyên gia không nhận token nào, và 1 - 1/hệ số phần cứng ngồi chờ. Có hai cách chữa và chúng khác nhau ở chỗ rất cụ thể. Mất mát phụ trợ can thiệp vào gradient, tức mua cân bằng bằng chất lượng. Điều chỉnh bias chỉ cộng một số vào điểm để xếp hạng, nên nó đổi được ai thắng mà không đổi một chữ số nào của trọng số trộn, và đó chính là topk_method: noaux_tc trong cấu hình DeepSeek-V3. Cách thứ hai vẫn có giới hạn: khi mọi token xếp hạng chuyên gia y hệt nhau thì bias chỉ dời được đống token chứ không chia nhỏ được nó.
- 1Một lô có 64 token, 16 chuyên gia, mỗi token chọn 2 chuyên gia. Chuyên gia đông nhất nhận 24 token. Hệ số mất cân bằng bằng bao nhiêu?
- 2Bạn nâng bias của chuyên gia 7 lên đủ lớn để nó lọt vào nhóm thắng của một token. Trọng số trộn mà token đó dành cho chuyên gia 7 được tính từ đâu?
- 3Một lô 32 token, 8 chuyên gia, mỗi token chọn 1, và mọi token đều xếp hạng các chuyên gia y hệt nhau. Chạy 12 bước điều chỉnh bias thì hệ số mất cân bằng đi tới đâu?