2 điểm bởi GN⁺ 2025-02-23 | 1 bình luận | Chia sẻ qua WhatsApp

Giới thiệu

  • Chào mừng đến với lớp học ngôn ngữ assembly của FFmpeg. Lớp học này cung cấp kiến thức nền tảng về cách assembly được viết trong FFmpeg.

Kiến thức cần thiết

  • Cần có kiến thức về ngôn ngữ C, đặc biệt là con trỏ.
  • Cần có kiến thức toán ở mức trung học phổ thông (scalar và vector, phép cộng, phép nhân, v.v.).

Assembly là gì?

  • Assembly là một ngôn ngữ lập trình dùng để viết mã tương ứng trực tiếp với các lệnh mà CPU xử lý.
  • Phần lớn mã assembly trong FFmpeg là SIMD (Single Instruction Multiple Data), còn được gọi là lập trình vector.
  • SIMD phù hợp để xử lý lượng lớn dữ liệu được lưu tuần tự trong bộ nhớ như hình ảnh, video và âm thanh.

Tại sao viết bằng assembly?

  • Để tăng tốc độ xử lý đa phương tiện. Khi viết bằng mã assembly, có thể đạt được mức cải thiện tốc độ hơn 10 lần.
  • Trong FFmpeg, người ta viết mã assembly trực tiếp thay vì dùng intrinsic. Intrinsic thường chậm hơn assembly viết tay khoảng 10-15%.

Các loại ngôn ngữ assembly

  • Bài học này tập trung vào ngôn ngữ assembly x86 64-bit. Nó còn được gọi là amd64 và cũng chạy trên CPU Intel.
  • Có hai kiểu cú pháp assembly x86 là AT&T và Intel, và ở đây sẽ sử dụng cú pháp Intel.

Tài liệu hỗ trợ

  • Lập trình assembly trong FFmpeg tập trung vào xử lý ảnh hiệu năng cao và có cách tiếp cận riêng.
  • Các sơ đồ trong sách "The Art of 64-bit assembly" có thể hữu ích.

Thanh ghi

  • Thanh ghi là vùng mà CPU dùng để xử lý dữ liệu. CPU không thao tác trực tiếp trên bộ nhớ mà nạp dữ liệu vào thanh ghi để xử lý rồi ghi trở lại bộ nhớ.

Thanh ghi đa dụng

  • Thanh ghi đa dụng (GPR) có thể chứa dữ liệu hoặc địa chỉ bộ nhớ. Trong mã assembly của FFmpeg, GPR chủ yếu đóng vai trò bàn đạp.

Thanh ghi vector

  • Thanh ghi vector (SIMD) chứa nhiều phần tử dữ liệu. Có nhiều loại thanh ghi vector khác nhau.
  • Phần lớn các phép tính nén và giải nén video là dựa trên số nguyên.

Bao gồm x86inc.asm

  • x86inc.asm là một lớp trừu tượng nhẹ được dùng trong FFmpeg, x264 và dav1d để giúp công việc của lập trình viên assembly trở nên dễ dàng hơn.

Mã assembly scalar đơn giản

  • Giải thích cách mã assembly scalar hoạt động thông qua mã ví dụ.

Hiểu hàm vector cơ bản

  • Giải thích ý nghĩa của từng dòng thông qua ví dụ về hàm SIMD đầu tiên.
  • Sử dụng các lệnh như movu, paddb để thực hiện phép toán vector.
  • Hàm sửa đổi dữ liệu của đối số và không trả về giá trị.

1 bình luận

 
GN⁺ 2025-02-23
Ý kiến Hacker News
  • Có thêm một tài liệu khác về cùng chủ đề là các trường hợp của FFmpeg và dav1d

    • FFmpeg được dùng rất thường xuyên nên có thể xem là một trường hợp sử dụng rõ ràng
    • dav1d được dùng trong các trình duyệt lớn và hệ điều hành Android, và một yếu tố lớn tạo nên thành công là SIMD viết thủ công
    • Một phần mã của dav1d được thực thi hàng nghìn tỷ lần mỗi ngày nên phải chạy nhanh nhất có thể
    • Chênh lệch hiệu năng giữa SIMD viết tay và SIMD do compiler sinh ra có thể lên tới 50%
    • Những tài nguyên như trường học assembly của FFmpeg rất quan trọng để duy trì các kỹ thuật này
  • Tôi nghĩ dùng intrinsic có giá trị hơn là viết assembly, nhưng việc đọc tài liệu này vẫn rất hữu ích

    • Dùng Compiler Explorer để hiểu những tối ưu mà compiler thực hiện nhằm tối ưu hiệu năng
  • Tôi thấy hướng dẫn này rất tuyệt vời

    • Giá mà tôi có hướng dẫn này khi còn quan tâm đến lập trình mức thấp
  • Tôi tò mò không biết việc học hay triển khai assembly có mang lại "niềm vui" nào không

    • Không biết nó có cái thú như LISP hay RISC-V, hay chỉ giống COBOL là học để làm việc với một hệ thống cụ thể
    • Trong công việc hằng ngày tôi không có lý do gì để dùng assembly, nhưng không biết có đáng bỏ thời gian ra học cho vui hay không
  • Hậu tố "q" biểu thị kích thước con trỏ, và trên hệ thống 64-bit thì là 8

    • Câu này tạo cảm giác khá khó hiểu
    • "i.e" nên được viết là "i.e.," và "(" nên là dấu ngoặc mở
    • "sizeof" không trả về con trỏ
  • Khen phần tham chiếu tới K&R

    • Đó là cuốn sách đầu tiên tôi mua để học C và lập trình
    • Ban đầu tôi học C++ nhưng nó quá trừu tượng nên khó hiểu
  • Nhược điểm của việc dùng assembly là mã nguồn phụ thuộc vào kiến trúc

    • Phải viết mã khác nhau cho x86, arm và x86_64
    • Không có cách tốt để viết mã SIMD có tính di động
    • Rust đang ổn định hóa API SIMD di động, còn Zig có hỗ trợ SIMD, nhưng FFmpeg có lẽ vẫn sẽ không hài lòng về tốc độ
  • Tôi thấy sự phản đối đối với inline assembly khá khó hiểu

    • Có vẻ inline assembly sẽ hiệu quả hơn so với gọi hàm assembly
  • Tài liệu này hoàn hảo

    • Tôi từng biết assembly x86 thời 386, nhưng các bộ xử lý cao cấp hơn thì quá phức tạp
    • Tôi muốn tìm hiểu thêm về SIMD trên CPU hiện đại
  • Tôi tự hỏi liệu chuyện assembly nhanh hơn C gấp 10 lần còn đúng không

    • Không biết compiler có đang chững lại đến mức không thể tiệm cận assembly viết tay hay không