1 điểm bởi GN⁺ 4 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Đã chạy Gemma 4 26B-A4B Q8_0 chỉ bằng CPU trên một máy chủ dùng dual Xeon E5-2690 v2 đời 2013 và DDR3, đạt khoảng 5,2 token/giây khi giải mã và khoảng 16 token/giây khi đánh giá prompt
  • Đường chạy tốc độ cao của ik_llama.cpp giả định có AVX2·FMA3, nhưng CPU Ivy Bridge chỉ hỗ trợ AVX1, nên cần sửa phần biên dịch và fallback phép toán cho bản build không AVX2
  • Graph builder tạo MOE_FUSED_UP_GATEFUSED_UP_GATE vô điều kiện, trong khi dispatcher không AVX2 không có đường xử lý, khiến mỗi lượt truyền xuôi có khoảng 240 tensor không được tính toán, dẫn đến đầu ra đa ngôn ngữ lộn xộn
  • Claude đã tìm ra lỗi bằng cách đo logit và phân tích mã, thay thế phép toán hợp nhất bằng hai lần ggml_mul_mat_idggml_fused_mul_unary; người dùng chạy thử nghiệm và xác định tiêu chí cho kết quả đúng
  • Máy chủ doanh nghiệp cũ vẫn có thể dùng làm phương án thay thế cục bộ khi API trả phí gặp sự cố hoặc cho các tác vụ batch chậm, nhưng không được dùng --run-time-repack vì nó tạo layout chỉ dành cho AVX2

Môi trường chạy trên máy chủ lưu trữ 13 năm tuổi

  • Thiết bị HP StoreVirtual được tái sử dụng dùng dual Xeon E5-2690 v2 đời 2013 và bộ nhớ DDR3, không có GPU
    • Thuộc thế hệ Ivy Bridge nên chỉ hỗ trợ AVX1, không hỗ trợ AVX2 và FMA3
    • Ban đầu được chế tạo để lưu trữ đĩa, chi phí mua dưới 300 USD
  • Mô hình chạy là Gemma 4 26B-A4B của Google, một mô hình mixture-of-experts (MoE) trọng số mở với 26 tỷ tham số
  • Trên mô hình lượng tử hóa Q8_0, tốc độ đo được là khoảng 5,2 token/giây khi giải mã và khoảng 16 token/giây khi đánh giá prompt

Trường hợp Xeon đời 2016 làm điểm xuất phát

  • A 10 year old Xeon is all you need được chia sẻ trên Hacker News là một trường hợp chạy Gemma 4 không cần GPU trên một Xeon đơn đời 2016 và 128GB DDR3
  • Cấu hình đó dùng ik_llama.cpp và khoảng 25 cờ chạy tinh chỉnh
    • Giải mã suy đoán
    • Định tuyến MoE có xét đến CPU
    • Flash attention cho CPU
    • Đóng gói lại trọng số khi chạy
  • Áp dụng cùng cách tiếp cận cho máy chủ Ivy Bridge, nhưng chương trình dừng ngay ở giai đoạn khởi động
    • Khác với CPU Broadwell đời 2016, E5-2690 v2 không có AVX2 và FMA3
    • Các tập lệnh này xuất hiện từ Haswell năm 2014, tức thế hệ v3 của Intel, và các kernel tốc độ cao được viết với giả định có chúng

Chẩn đoán và vá lỗi bằng Claude

  • Sau khi nhận thông tin lỗi khởi động, Claude xác định nguyên nhân là khác biệt về tập lệnh CPU
  • Tiếp nối một cách tiếp cận chưa hoàn chỉnh từng thử với mô hình miễn phí, Claude sửa để các đường C++ quan trọng về hiệu năng fallback đúng trên CPU trước AVX2
  • Công việc không kết thúc bằng một yêu cầu fix it duy nhất
    • Đọc mã C++ thiên về hiệu năng do nhà phát triển khác viết
    • Phân tích vì sao kernel không hợp lệ trên một vi kiến trúc cụ thể
    • Né các đường không được hỗ trợ mà không bỏ các tối ưu hóa sẵn có của fork
  • Thay vì tự viết fallback kernel C++, người dùng chạy thử nghiệm, đọc đầu ra, quyết định câu hỏi tiếp theo và đóng vai trò xác định tiêu chí cho kết quả đúng
  • Việc chẩn đoán và vá lỗi được thực hiện bởi một instance Claude chạy trên chính máy chủ đó

Đường phép toán bị hỏng trong bản build không AVX2

  • ik_llama.cpp dùng cho suy luận Gemma 4 MoE là một fork của llama.cpp, về mặc định giả định AVX2 là điều kiện tối thiểu
  • Khi tắt GGML_USE_IQK_MULMAT lúc build, hầu hết đường tốc độ cao bị loại trừ và fallback về phép toán scalar/SSE thông thường
    • Fallback này hoạt động với phép nhân ma trận Q8_0 thông thường
    • Tuy nhiên fallback không được áp dụng cho hai phép toán đồ thị
  • Mạng feedforward MoE của Gemma 4 tạo ra các phép toán sau
    • MOE_FUSED_UP_GATE: phép toán kết hợp phép nhân ma trận gate·up theo từng expert và SwiGLU
    • FUSED_UP_GATE: phiên bản phép toán dense dùng trong các tầng không MoE
  • Hai phép toán trong compute dispatcher được bảo vệ bằng điều kiện GGML_USE_IQK_MULMAT, nhưng graph builder lại tạo phép toán không điều kiện
    • Dispatcher của bản build không AVX2 không có case xử lý enum tương ứng
    • Phép toán rơi vào nhánh mặc định, khiến tensor đích của mọi mạng feedforward expert âm thầm không được tính toán
  • Gemma 4 26B dùng 8 expert hoạt động cho mỗi token trên 30 tầng, nên mỗi lượt truyền xuôi tiêu thụ khoảng 240 tensor chứa các giá trị còn sót trong buffer bộ nhớ

Manh mối lộ ra từ đầu ra lộn xộn

  • Đầu ra lỗi trông có vẻ trôi chảy nhưng là chuỗi đa ngôn ngữ vô nghĩa
    • Token ID phân bố đều trên toàn bộ 262.000 mục từ vựng
    • Tiếng Thái, tiếng Hàn, sentinel <unused>, mảnh tiếng Anh, v.v. được tạo với tần suất tương tự nhau
  • Ở nhiệt độ 0, đầu ra có tính quyết định; kết quả chạy đơn luồng và đa luồng cũng giống nhau đến từng byte và không xuất hiện NaN
  • Dạng lỗi cho thấy các hằng số lớn ở từng tầng đẩy trạng thái ẩn, khiến softmax cuối cùng trở nên phẳng
  • Claude đo logit thô trước bước sampling để in ra 5 token đứng đầu, phạm vi, trung bình và số lượng NaN
    • Logit trung bình của token dự đoán đầu tiên không nằm gần 0 mà là +16
    • Khoảng 80% toàn bộ từ vựng có logit dương
  • Vì độ lệch là ổn định chứ không giống hư hỏng ngẫu nhiên, phạm vi được thu hẹp vào việc phần lớn trạng thái ẩn đang dùng bộ nhớ chưa khởi tạo còn lại các giá trị dấu phẩy động dương nhỏ

Bản sửa gồm ba bước

  • Bản vá gồm ba commit đặt trên main của fork
  • Sửa biên dịch không AVX2

    • Nhánh scalar #else trong quantize_row_q8_0_x4quantize_row_q8_1_x4_T của iqk_quantize.cpp thực tế vẫn tham chiếu các helper AVX2 như hsum_i32_8
    • Viết lại nhánh đó thành vòng lặp scalar có tính portable
    • Thêm điều kiện bảo vệ #if GGML_USE_IQK_MULMAT cho một số lời gọi IQK bị rò sang ggml.cggml-quants.c
    • Thêm include bị thiếu để iqk_cpu_ops.cpp có thể biên dịch độc lập
    • Nếu không có sửa đổi này, bản fork tự nó không build được trên phần cứng không AVX2
  • Fallback đồ thị khi chạy

    • Thay vì sửa dispatcher, thay đổi graph builder để trong bản build này nó tạo các phép toán đã có đường tính toán
    • Trong ggml_moe_up_gate, xử lý trọng số up_gate_exps đã kết hợp khi GGML_USE_IQK_MULMAT bị tắt
    • Dạng tensor là [n_embd, 2*n_ff, n_experts], trong đó nửa đầu là gate, nửa sau là up
    • Tách bằng hai lát ggml_view_3d
    • Chạy ggml_mul_mat_id trên từng lát
    • Kết hợp hai kết quả bằng ggml_fused_mul_unary(gate, up, SILU)
    • Nếu trọng số gate và up đã được tách sẵn, dùng hai lần ggml_mul_mat_id và phép nhân hợp nhất·phép toán đơn ngôi mà không cần lát cắt
    • Áp dụng fallback tương tự cho ggml_fused_up_gate dùng trong các tầng không MoE
    • mul_mat_id dùng triển khai ggml mặc định, còn fused_mul_unary xử lý SILU và phép nhân trong một lần, nên mọi phép toán cấu thành đều đã có triển khai không IQK
    • Toàn bộ thay đổi nằm sau #if !GGML_USE_IQK_MULMAT, nên kết quả của bản build AVX2 vẫn giống bit-for-bit như trước
  • Dọn dẹp stub CI

    • Stub #else trong mã nguồn IQK khác với iqk_mul_mat.h, khiến ci/run.sh cũng không build được trên phần cứng không AVX2
    • Thiếu include <cstdint>
    • Một số stub có chữ ký khác nhau, như có tham số đầu không cần thiết hoặc thiếu tham số sinks
    • Một số hàm không có stub, gây tham chiếu chưa được định nghĩa ở bước liên kết
    • Sau khi căn stub khớp với header, test suite cũng có thể chạy trong môi trường không AVX2

Chi phí hiệu năng của fallback và lỗi repack

  • Fallback phát sinh chi phí bổ sung vì chạy hai lần mul_mat_id thay cho một kernel hợp nhất
  • CPU này vốn đã bị giới hạn bởi băng thông bộ nhớ, còn kernel hợp nhất ban đầu cũng chỉ dành cho AVX2, nên trong môi trường này không có đường chạy hiện hữu nào bị từ bỏ
  • Hiệu năng cuối cùng trên MoE 26B-A4B là khoảng 5,2 token/giây khi giải mã và khoảng 16 token/giây khi đánh giá prompt
  • --run-time-repack sắp xếp lại trọng số lượng tử hóa thành định dạng xen kẽ chỉ dành cho AVX2, Q8_0_R8, khi khởi động
    • Đây là một bug riêng làm hỏng lại đầu ra trong môi trường AVX1
    • Bản vá hiện tại không sửa lỗi này và loại bỏ cờ đó khỏi script chạy

Quá trình thu hẹp nguyên nhân

  • Sự không khớp về tập lệnh dễ xác nhận, nhưng việc dispatcher rơi vào nhánh mặc định mà không báo lỗi thì khó tìm hơn
  • Qua rà soát mã, nhiều ứng viên đã bị loại trừ
    • Helper RMSNorm trông đúng
    • Fallback AVX1 của ggml_vec_dot_q8_0_q8_0 cũng trông đúng
    • Kết quả đơn luồng giống bit-for-bit giúp loại trừ lỗi threading
  • Việc logit trung bình cố định ở +16 và các token đuôi dài có giá trị tương tự nhau cho thấy phần lớn residual stream chưa được khởi tạo
  • Sau khi tìm #if GGML_USE_IQK_MULMAT trong dispatcher, hai đường phép toán bị thiếu được phát hiện trong khoảng 1 phút

Điều kiện tái hiện và phạm vi sử dụng

  • Điều kiện tái hiện trên thiết bị trước AVX2 như sau
    • Phần cứng: dual Xeon E5-2690 v2, Ivy Bridge, AVX1, DDR3, không GPU
    • Build: biên dịch ik_llama.cpp từ nhánh vá lỗi không có GGML_USE_IQK_MULMAT
    • Mô hình: Gemma 4 26B-A4B Q8_0
    • Chạy: dùng các cờ CPU thông thường của ik_llama.cpp nhưng loại trừ --run-time-repack
  • Có thể xem thay đổi chính xác tại ikawrakow/ik_llama.cpp PR #2138
    • Tại thời điểm viết, PR vẫn đang mở và chờ maintainer xem xét, nên cần chạy trực tiếp từ branch
    • Bug xảy ra trên cùng thiết bị có thể được báo trong luồng PR
  • Duy trì mô hình cục bộ trên máy chủ doanh nghiệp cũ có thể dùng làm phương án thay thế khi API trả phí bị gián đoạn, hoặc xử lý các tác vụ batch chậm không phù hợp với cách tính phí theo token
  • Bài viết coi trọng năng lực tự đào sâu vào mã lạ và hệ thống cũ hơn là dùng dịch vụ thuê bao; cách này cũng áp dụng tương tự cho việc bảo trì ứng dụng Rails 15 năm tuổi hoặc cơ sở dữ liệu mà người phụ trách đã rời đi

1 bình luận

 
Ý kiến trên Hacker News
  • Dự đoán rằng đến giữa năm 2027, mô hình MoE vượt 200 tỷ tham số sẽ có thể chạy trên phần cứng tiêu dùng phổ thông
    Đang chạy Qwen3.6-35B-A3B cục bộ trên Mac 16GB và đạt 7–9 token/giây: https://github.com/deepanwadhwa/samosa-chat
    Nghĩa là một mô hình cấp độ GPT-4 đang chạy cục bộ trên MacBook Air 16GB với tốc độ như vậy

    • Có lẽ thậm chí không cần đợi đến lúc đó. Mô hình trọng số tam phân Bonsai 27B mà Prism công bố vài ngày trước chỉ khoảng 7GB và cho hơn 44 token/giây trên laptop M4 Max: https://huggingface.co/prism-ml/Ternary-Bonsai-27B-mlx-2bit
      Nó đã nằm trong cùng khoảng số tham số hoạt hóa với phần lớn các mô hình trên 200 tỷ tham số, nên nếu Prism muốn thì họ có thể tung ra một mô hình như vậy. Tuy nhiên, mạng nơ-ron hồi quy như HRM không cần nhiều tham số đến thế, nên việc quy mô đó có thực sự cần thiết hay không vẫn còn có thể tranh luận: https://huggingface.co/sapientinc/HRM-Text-1B
    • 7–9 token/giây khó có thể xem là tốc độ ổn. Tôi không phải chuyên gia, nhưng khi thử chạy cục bộ thì dưới 12–16 token/giây là đã thấy khó chịu
    • Nhìn chung tôi đồng ý với dự đoán, nhưng cho rằng mốc thời gian có thể muộn hơn một chút. Để đạt được điều đó sẽ cần kiểu nén hoàn toàn khác với cách giảm số bit trên mỗi tham số hiện nay, nên trong bối cảnh đó bản thân thước đo số lượng tham số có thể không còn nhiều ý nghĩa
      Ví dụ, nếu mỗi tầng chỉ có một seed 256-bit rồi đưa vào hàm nhiễu để sinh ra 16K trọng số thực, thì dung lượng lưu trữ trên mỗi trọng số có thể giảm xuống dưới 1 bit
    • Tôi đang chạy Ornith 35B trên Pi và đạt hơn 50 token/giây. Từ khi biết Pi còn hỗ trợ tìm kiếm và truy xuất, tôi không còn thấy cần tìm mô hình lớn cho việc tìm kiếm nữa
      Có vẻ trong tháng này và tháng sau sẽ liên tiếp có các mô hình mới làm thay đổi cuộc chơi, nên khá háo hức. Ornith thực sự đáng thử
    • 9 token/giây có vẻ rất khó chịu để dùng. Chuyện dùng đến 1 triệu token trong chưa đầy một ngày với một phiên Claude là khá bình thường, nên cho công việc thực tế thì có vẻ quá chậm
  • Dù có người không thích nghe, tôi nghĩ chi phí token của nhà cung cấp suy luận rẻ hơn tiền điện để chạy cục bộ
    Nếu đơn giản hóa và chỉ tính phần sinh đầu ra, thì 5 token/giây là 18.000 token/giờ, và chi phí từ nhà cung cấp chỉ khoảng 0,005 USD. Giả sử máy chủ dùng khoảng 500W khi suy luận và lấy Đức làm chuẩn với giá điện 0,3 USD/kWh, thì tạo ra cùng lượng đó cục bộ sẽ tốn 0,15 USD, tức đắt hơn 30 lần
    Nếu lo ngại quyền riêng tư thì chạy cục bộ vẫn là lựa chọn tốt, nhưng cần hiểu rằng nó kém hiệu quả hơn rất nhiều so với nhà cung cấp suy luận. Khi GPU mới tiếp tục nâng hiệu suất suy luận, khoảng cách này sẽ còn nới rộng đáng kể
    Ban đầu tôi tính nhầm thành 180.000 token, nhưng thực tế là 18.000 token, nên trừ khi điện gần như miễn phí thì rất khó cạnh tranh. Các nhà cung cấp cũng vẫn đang dùng H200/H100 cho các mô hình nhỏ, nhưng khi chuyển sang GB300 hay GPU Ruby vào năm sau, chi phí suy luận có thể giảm thêm 30 lần, và giá trị chính của mô hình cục bộ có lẽ sẽ là quyền riêng tư

    • Ở nhà tôi chạy Qwen 27B thì lúc làm việc tiêu thụ khoảng 400W, tốc độ sinh khoảng 40 token/giây, còn phần xử lý prompt quan trọng hơn đạt khoảng 1.000 token/giây
      Trong một giờ, nó có thể xử lý 3,6 triệu token đầu vào hoặc sinh 144.000 token, với tiền điện khoảng 0,15 USD. Nếu dùng Sonnet cho cùng khối lượng đó thì đầu vào là 7,2 USD và phần sinh là 1,4 USD, nghĩa là cloud đắt hơn 10 lần ở phần sinh và gần 50 lần ở phần xử lý
    • Ở Mỹ thì giá điện còn không gần mức 0,30 USD/kWh. Vào giờ thấp điểm chỉ bằng một nửa, và bạn còn có thể đầu tư 1.000 USD vào pin để lưu trữ điện giá 0,11 USD vào lúc cực rẻ
      Các nhà cung cấp suy luận đang gánh khoản nợ khổng lồ và cạnh tranh giành thị phần, nên giá chắc chắn sẽ tăng
    • Sẽ rất hay nếu làm một máy chủ LLM tự host độc lập chạy bằng năng lượng mặt trời và pin. Giống như Low Tech Magazine, nó sẽ offline khi thiếu nắng, và được xây dựng ở quy mô đủ cho cộng đồng địa phương như nhóm bạn, khu phố hay câu lạc bộ dùng hằng ngày
      Nếu AI được dân chủ hóa đến mức cộng đồng có thể trực tiếp kiểm soát, thì vấn đề trung tâm dữ liệu cũng được giải quyết, còn mức độ kiểm duyệt và căn chỉnh cũng có thể do cộng đồng quyết định một cách dân chủ. Đây là ý tưởng khá giống một số bài viết của Geohotz
      Các mô hình mã nguồn mở sắp đủ tốt và đủ hiệu quả để có thể phục vụ rẻ bằng phần cứng cũ. Mỗi cộng đồng nhỏ chỉ cần một người rành kỹ thuật huy động vài trăm USD chi phí ban đầu, rồi sau đó có thể vận hành gần như miễn phí ngoài điện
      https://solar.lowtechmagazine.com/
    • Hiệu suất là quan trọng, nhưng cũng có nhiều người có điện rẻ hoặc thiết bị hiệu quả. Trên home server AMD Strix Halo, chỉ dùng 100W mà vẫn có thể phục vụ Gemma4-26B ở khoảng 70 token/giây
    • Tôi không quan tâm việc nó có tốn hơn hay không. Lý do chạy cục bộ không phải để tiết kiệm tiền mà là để có được tự do và quyền riêng tư, và việc tồn tại lựa chọn đó cũng giúp giảm chi phí về lâu dài
      Nếu không có phương án thay thế là cục bộ, giá của các mô hình cloud sẽ còn đắt hơn nhiều
  • Thế hệ dual Xeon này khi có tải rất dễ tiêu thụ hơn 300W. Với giá điện trung bình ở Mỹ thì tốn 1,35 USD mỗi ngày, và nếu mùa hè còn phải làm mát không gian thì chi phí sẽ tăng thêm
    Bỏ qua thời gian xử lý prompt, chạy 24 giờ cũng chỉ được khoảng 400 nghìn token mỗi ngày, nên chi phí rơi vào khoảng 0,30 USD cho mỗi 1 triệu token đầu ra. Trùng hợp là mức này đúng bằng giá hiện tại của model trên OpenRouter, nhưng tốc độ sinh của OpenRouter thì nhanh hơn 8 lần
    Có nhiều lý do để thử nghiệm LLM cục bộ, như giữ dữ liệu không rời khỏi nhà, nhưng để có lợi về tiền bạc thì khá khó. Với tư cách là người đã đầu tư nhiều tiền hơn rất nhiều vào dàn suy luận cục bộ ở nhà, tôi thấy nó vui thì có vui nhưng không phải là cách để tiết kiệm

    • Với người sống trong nhà riêng thực tế thì đây là cách tính hợp lý. Tôi sống ở nhà thuê và không tự trả tiền điện, nên ranh giới hiệu quả chi phí là thời điểm chủ nhà bắt đầu phàn nàn
    • Tôi nghĩ đa số không chạy model cục bộ để tiết kiệm tiền, mà là để không phát tán dữ liệu riêng tư
    • Nó giống tiền mã hóa. Vì tiền điện, với đa số mọi người thì mua vẫn rẻ hơn tự đào
    • Vào mùa lạnh khi ở nhà phải bật sưởi, nhiệt thải cũng dùng được nên hiệu quả kinh tế sẽ tốt hơn
  • Đã tổng hợp kết quả chạy nhiều model trên dual Xeon và DDR4 256GB mà không có GPU
    https://gist.github.com/hparadiz/f3596d00a62d8ebb2dadcc46ee5822c7

    • Tò mò không biết có thử chỉ dùng một CPU để loại bỏ suy giảm hiệu năng NUMA hay chưa. Khi đó sẽ chỉ dùng được một nửa bộ nhớ, nhưng tôi muốn biết chênh lệch hiệu năng là bao nhiêu
    • Có vẻ nếu có thật nhiều RAM chậm thì cả model nhỏ cũng chạy khá nhanh. Tò mò không biết model lớn hơn sẽ hoạt động thế nào trên dàn này
  • Khá chậm. Tôi đang đạt 8~12 token/giây ngay cả trên CPU 13 năm tuổi, dù còn phụ thuộc vào kích thước ngữ cảnh và các thiết lập khác
    https://news.ycombinator.com/item?id=48354801

    • Ngay cả với Xeon E3-1270 V2 3.50GHz và Nvidia Quadro K2200 4GB cũ cũng ra 8~9 token/giây. Tôi đang chạy gemma4:e2b và gemma4:12b-it-qat trên Ollama
    • Có phải khác biệt là bài gốc dùng lượng tử hóa Q8 còn ở đây dùng Q4 không?
  • Tôi là tác giả bài gốc. Có vẻ bình luận ban đầu đã bị report vì lý do nào đó. Tôi đã mở phần chỉnh sửa trong PR #2138 của dự án upstream: https://github.com/ikawrakow/ik_llama.cpp/pull/2138

  • Có vẻ thiết bị StoreVirtual này không có cổng nào đủ hữu ích để cài phần mềm. Chỉ thấy cỡ như cổng USB, nên tôi thắc mắc không biết có phải cài qua serial console không

  • Tôi đang chạy Gemma 4 26B trên Mac Pro 2013 với cùng cấu hình và đạt khoảng 5 token/giây. Card đồ họa kép ở đây không có ích, nhưng với một số tác vụ thì vẫn đủ thực dụng

  • Tôi đã tận mắt thấy dàn máy trong tầng hầm, thật sự rất ấn tượng. Lần tới mong bạn cũng giới thiệu cả máy in 3D

  • Một video hơi liên quan: chạy LLM trên Pentium 4 và đặt biệt danh là NetburstGPT. Tất nhiên là rất chậm
    https://www.youtube.com/watch?v=ILV-eu90te8