Show HN: Khả năng tăng tốc suy luận LLM lên gấp 2 lần (Speeding up LLM inference 2x times (possibly))
(asciinema.org)Effort là gì?
- Effort là năng lượng, thời gian và tài nguyên được投入 để hoàn thành một việc hoặc đạt được mục tiêu
- Nó có nghĩa là sự nỗ lực và công sức cần thiết để vượt qua trở ngại hoặc đạt được kết quả mong muốn
- Effort có thể mang tính thể chất hoặc tinh thần
- Nỗ lực thể chất như năng lượng dùng để nâng vật nặng hoặc chạy marathon
- Nỗ lực tinh thần như sự tập trung và sức mạnh tinh thần cần thiết để giải quyết vấn đề phức tạp hoặc học kỹ năng mới
- Đây là yếu tố cốt lõi để đạt được thành công trong nhiều lĩnh vực của cuộc sống như phát triển cá nhân, công việc và giáo dục
Ý kiến của GN⁺
- Effort không chỉ đơn giản là lượng thời gian hay năng lượng bỏ vào, mà còn là khái niệm chịu tác động tổng hợp của nhiều yếu tố như tính bền bỉ, sự tập trung và động lực. Vì vậy, chỉ chăm chỉ thôi cũng không đảm bảo chắc chắn thành công
- Đặc biệt với các công việc đòi hỏi Effort về mặt tinh thần, cần chú ý để không rơi vào tình trạng kiệt sức. Điều quan trọng là tìm ra cách duy trì Effort thông qua nghỉ ngơi và phần thưởng phù hợp
- Mỗi người có thể có cách投入 Effort khác nhau. Có người tập trung cao độ trong thời gian ngắn, có người lại duy trì Effort đều đặn trong dài hạn. Tìm ra phương pháp phù hợp với bản thân sẽ hiệu quả hơn
1 bình luận
Các ý kiến trên Hacker News
Cốt lõi của thuật toán có vẻ là cắt tỉa tham số trong lúc chạy, xác định các trọng số kém quan trọng hơn theo thứ hạng giá trị tuyệt đối của các trọng số cần cắt tỉa trong từng nhóm, rồi đặt chúng về 0 để làm thưa ma trận trọng số
Nếu tìm kiếm về cắt tỉa mô hình thì sẽ ra rất nhiều kết quả, và https://arxiv.org/abs/2305.11627 cũng xem “cắt tỉa dựa trên độ lớn” là đường cơ sở và trích dẫn https://arxiv.org/pdf/2301.00774.pdf
Tôi không thích kiểu các bài báo triển khai đường cơ sở một cách sơ sài rồi khoe phương pháp của mình, hoặc dùng đầy thuật ngữ toán học để bao bọc cho nó. Bài blog gốc truyền đạt phương pháp dễ hiểu hơn nhiều, kể cả với người gần như không có kiến thức nền
Cách tiếp cận trong các bài báo được nhắc tới có vẻ là dạng tĩnh, và dường như họ không đưa ra thuật toán nào thực sự tăng tốc tính toán với kết quả 20–50%. Đó là một phần lớn của phần khó. Khi nào có thời gian tôi định sẽ đọc kỹ các tài liệu liên quan
Cuối cùng tôi muốn thêm một trang trích dẫn cùng với các bài báo mà mọi người đăng trong phần bình luận. Tôi nghĩ có thể sớm muộn cũng sẽ có ai đó tìm ra một bài đã mô tả thuật toán này rồi
Trong quá trình phát triển, tôi cũng đã hỏi gpt-4 và tìm trên Google, nhưng những thứ tôi tìm được phần lớn là tĩnh hoặc theo hướng tùy ý loại bỏ toàn bộ chiều/layer rồi huấn luyện lại. Tôi không tìm thấy thứ nào khớp chính xác với ý tưởng này
Bài viết càng dày đặc và khó hiểu thì khả năng nó đang che giấu khoa học kém chất lượng bên trong càng cao
Tôi thích câu này trong phần triển khai GPU
“Độc giả mới làm quen với lập trình GPU giờ có thể hỏi: cái này hoạt động thế nào?
Độc giả có kinh nghiệm lập trình GPU có thể hỏi: rốt cuộc cái này hoạt động thế nào?”
Sẽ rất tốt nếu có ai đó thật sự rành Metal review đoạn code này. Đây là lần đầu tôi thử lập trình GPU
“Hãy lật ma trận, sắp xếp các phần tử theo từng hàng, rồi nhìn lại phép nhân theo hướng đó. Những người thông minh gọi đây là định dạng hàng thưa nén (CSR). Bây giờ để nhân, ta lấy giá trị 1 của vector, nhân với 256, rồi cộng vào hàng thứ 3 của vector đầu ra, cứ thế tiếp tục. Giờ hãy xem điều gì xảy ra nếu ta cắt bỏ cột cuối cùng chứa các giá trị thấp nhất.”
Tôi tò mò điều này khớp với cách CSR giảm số phép nhân như thế nào
Cách này trông giống độ thưa bán cấu trúc, còn gọi là độ thưa 2:4, nên đáng được so sánh trực tiếp. Theo tôi đọc lướt, kỹ thuật này được tối ưu cho Apple Silicon, nhanh hơn khoảng 2 lần ở mức thưa 75%, là phương pháp động được áp dụng lúc chạy tùy theo đầu vào, và có thể chọn mức độ thưa
Trong khi đó, độ thưa bán cấu trúc 2:4 được tối ưu cho GPU có sparse tensor core, tức Nvidia Ampere trở về sau, nhanh hơn khoảng 2 lần ở mức thưa 50%, là phương pháp tĩnh áp dụng ở trạng thái lưu trữ của mô hình, và ở mức thưa 50% có khả năng cho kết quả kém hơn kỹ thuật này
So sánh tôi muốn thấy là kết quả tăng tốc 2 lần với độ thưa 50% của độ thưa bán cấu trúc, so với kết quả tăng tốc 2 lần với độ thưa 75% của kỹ thuật này
Tôi chọn Apple Silicon vì dễ phát triển. Thuật toán này có khả năng cũng đạt hiệu năng tốt trên các kiến trúc khác
Với tư cách người từng dùng CSR, tôi không thấy ngạc nhiên. Trong các định dạng mới hơn, có thể có những định dạng phù hợp hơn với đặc tính phần cứng, như block ELL
Những định dạng đó tránh các lần đọc không được hợp nhất hoặc gather, nhưng code sẽ phức tạp hơn
bucketMul hầu như không có các lần đọc không được hợp nhất và dùng cấu trúc dữ liệu khác với CSR thông thường. Nó được giải thích ở đây: https://kolinko.github.io/effort/bucketmul.html
Mỗi hàng ma trận được chia thành 16 phần, rồi chọn phần nào cần đọc. Việc ghi hoàn toàn tuyến tính
Tuy nhiên tôi không chắc những gì mình nói lúc này có hợp lý không. Hôm nay đã hơi muộn và là một ngày dài
Ý tưởng và bài viết hay. Tôi cũng đang làm về mảng thưa trong suy luận mạng nơ-ron, và nghĩ ra vài điểm đáng lưu ý
So với triển khai phép nhân ma trận-vector dày đặc, thuật toán này tăng thêm độ phức tạp thuật toán nhưng giảm lưu lượng bộ nhớ. Phép nhân ma trận-vector thường bị nghẽn ở bộ nhớ, nên giảm truy cập bộ nhớ sẽ làm tăng thông lượng. Tuy nhiên, khi kích thước batch lớn hơn 1, truy cập bộ nhớ không còn là nút thắt nữa, nên khả năng tăng tốc rất dễ biến mất rất nhanh
Về đối tượng so sánh, tôi muốn thấy không chỉ cùng một mô hình, mà cả các mô hình khác có kiến trúc nhanh hơn 2 lần. Ví dụ, khi áp dụng phương pháp này với độ thưa 50% cho LLM 13B tham số, kết quả so với LLM 7B tham số sẽ thế nào; hoặc so với cùng LLM đó được lượng tử hóa xuống một nửa độ rộng bit chuẩn thì ra sao. Nếu trong cùng khoảng thời gian mà nó cho đầu ra có độ trung thực cao hơn các framework suy luận hiện có, thì đây có vẻ là chất liệu cho một bài báo thú vị
Vì bỏ qua phép nhân, sai số xấp xỉ có khả năng bị lệch theo hướng giá trị tuyệt đối luôn nhỏ hơn kết quả thực tế. Nếu có thể thêm một hạng hiệu chỉnh để bù sai số hệ thống đó, hiệu năng có lẽ sẽ tốt hơn một chút
Ký hiệu Big-O không thật sự rất phù hợp với tác vụ GPU, nhưng trong trường hợp này thì đại khái đúng
Vấn đề chính là giới hạn kiến trúc của GPU. Thuật toán này cần nhiều register/threadgroup/bộ nhớ cache hơn cách truyền thống, và đó trở thành nút thắt chính. Ngoài ra, vì mọi phép nhân đều dùng các bucket khác nhau, nên việc song song hóa tác vụ không đơn giản như các mô hình MoE
Với các kiến trúc lớn hơn, tôi đã thử khá nhiều trên Mixtral, về cơ bản là một mô hình 13B, và cảm giác của tôi là nó trụ tốt hơn nhiều ở đó. Tốc độ suy luận theo effort vẫn được duy trì, còn chất lượng theo effort vẫn cho kết quả đọc được ở mức 12–16% chứ không phải 20–25%. Thử nghiệm còn hạn chế, và trong lúc thêm triển khai Mistral tôi đã làm hỏng triển khai Mixtral nên chưa có dữ liệu chắc chắn, nhưng tôi sẽ sớm sửa
Theo trực giác, mô hình càng lớn thì càng có thể cắt giảm effort nhiều hơn
Ban đầu tôi cũng đoán rằng bỏ qua phép nhân sẽ tạo ra thiên lệch, nhưng trái với trực giác, chuyện đó không xảy ra. Tôi có vài biểu đồ nhưng chưa chuẩn bị để công bố
Vì các giá trị trong ma trận phân bố khá đều giữa số dương và số âm, nên sau một ngưỡng nhất định, độ trôi của kết quả không lớn
Trông rất tuyệt. Tuy nhiên, độ trễ 15ms khá gần với 16,7ms của đồng bộ dọc 60Hz
Nếu bạn đang cập nhật màn hình theo từng token, có thể có chỗ nào đó đang bị đồng bộ
Dù sao cũng cảm ơn ý tưởng. Tôi sẽ xem đó là đóng góp đầu tiên từ cộng đồng :D
Thật sự là một đóng góp tuyệt vời và cởi mở. Tôi sẽ theo dõi sát xem llama.cpp có triển khai cái này không
Tôi đang tìm cách tăng tốc suy luận trên CPU, và rất thích ý tưởng effort
Cái tên là do chatgpt gợi ý. Khi nó nói không nhận ra cách tiếp cận này, có khả năng đây thật sự là thứ mới
Tôi muốn liên hệ với llama.cpp và các dự án khác, và hy vọng nó được triển khai. Tôi cũng từng nghĩ đến việc tự viết patch cho llama, nhưng C++ và quy mô của dự án đó hơi quá sức với tôi
Suy luận trên CPU cũng sẽ nhanh hơn tương tự. Hơn nữa, vì có thể chỉ tải một phần trọng số, ví dụ bỏ qua những phần kém quan trọng hơn và chỉ tải 70%, nên có thể chạy mô hình với ít VRAM hơn trước. Tuy nhiên vẫn cần triển khai Q8
Thú vị là khi tôi cố so sánh benchmark với llama.cpp, tôi không tìm được tốc độ 7B/FP16 trên MB Air 16GB. Lý do là theo cách thông thường thì không thể chạy được. Với Effort thì có thể
Tương tự, tôi đã chạy Mixtral ở độ phân giải đầy đủ nhưng bị cắt bớt trên M2 96GB. Bình thường cần 114GB RAM, nhưng vì chỉ tải 75% trọng số nên nó chạy mượt. Hiện tại tôi đã làm hỏng triển khai một chút nên nó đang xuất ra rác, cần sửa lại
Bài viết hay. Tôi rất tò mò hiệu năng trên mỗi VRAM so với lượng tử hóa đơn giản sẽ như thế nào
Cũng tò mò liệu có kế hoạch triển khai phiên bản đa nền tảng không
Tất nhiên cũng có thể tải ít trọng số hơn, nhưng có vẻ nếu bỏ bớt hơn 20–30% trọng số thì chất lượng giảm rất nhanh
Nói cách khác, thuật toán này tách thời gian suy luận khỏi mức sử dụng VRAM
Dù vậy, tôi cũng tò mò liệu với effort, Q8 bị cắt còn 75% có thể cho kết quả tốt hơn Q6 hay không
Nhưng có lẽ vẫn cần vài tuần nữa để tinh chỉnh triển khai đủ tốt và kiểm thử đúng cách
Cách này không cần huấn luyện lại, nhưng tôi tò mò liệu có thể dùng cách tiếp cận này cùng với lượng tử hóa, rồi sau đó huấn luyện bổ sung để lấy lại một phần chất lượng đã mất hay không
Thật vui khi thấy những thứ như thế này, và thật thú vị khi hình dung hiệu năng và chi phí có thể còn cải thiện đến mức nào trong tương lai. Cảm ơn vì đã phát triển dưới dạng mã nguồn mở
Một là hậu huấn luyện sau đó, cách còn lại là lượng tử hóa trong quá trình huấn luyện nhưng giữ activation và gradient ở độ chính xác đầy đủ, gọi là huấn luyện nhận biết lượng tử hóa