Những hiểu lầm phổ biến về compiler
(sbaziotis.com)Những hiểu lầm về tối ưu hóa compiler
- Tối ưu hóa sẽ tạo ra chương trình tối ưu?
- Mục tiêu của compiler không phải là tạo ra chương trình tối ưu tuyệt đối, mà là cải thiện một chương trình đã được đơn giản hóa.
- Có thể tối ưu kích thước mã, nhưng tối ưu thời gian chạy thì khó hơn do khó đo lường, thiếu cấu trúc con tối ưu và mô hình phần cứng không chính xác.
- Không giống như kích thước mã, thời gian chạy rất khó đo chính xác, bị ảnh hưởng bởi nhiều yếu tố và không có cấu trúc con tối ưu. Ví dụ, dù tối ưu riêng từng vòng lặp, để tối ưu toàn bộ chương trình có thể vẫn cần gộp hai vòng lặp đó lại. Ngoài ra, việc tối ưu còn khó vì không có mô hình chính xác cho phần cứng đích. Chẳng hạn, goSLP tạo ra mã vector hóa SLP được tối ưu ở phạm vi toàn cục, nhưng do mô hình phần cứng không chính xác, chương trình được tạo ra không những không tối ưu mà thậm chí có thể chậm hơn LLVM.
Những hiểu lầm liên quan đến dự đoán nhánh
- Trọng số nhánh được dùng bởi bộ dự đoán nhánh của CPU?
- Trên kiến trúc x86, compiler không tạo branch hint.
- Trọng số nhánh được dùng để compiler bố trí các khối mã. (Ví dụ: nếu khả năng rẽ nhánh cao, khối đích sẽ được đặt ngay bên dưới khối hiện tại để tăng tính cục bộ của instruction cache)
- Trên kiến trúc Intel Redwood Cove gần đây, branch hint lại trở nên có ý nghĩa, nhưng trên thực tế compiler hiếm khi tạo ra các hint như vậy.
Những hiểu lầm về mức tối ưu hóa
-O3tạo ra mã nhanh hơn-O2rất nhiều?- Với Clang, chênh lệch hiệu năng giữa
-O2và-O3không lớn; với GCC,-O2kém quyết liệt hơn Clang nên có khác biệt đôi chút. -O3hầu như không cân nhắc đến kích thước mã, nên có thể gây ra vấn đề với instruction cache.- Tốt nhất là kiểm chứng bằng benchmark.
- Với Clang, chênh lệch hiệu năng giữa
Những hiểu lầm về Javascript interpreter và JIT compiler
- Javascript interpreter thực hiện JIT compilation ở runtime vì không thể biết trước đường đi nào là hot?
- Chỉ biết hot path là chưa đủ; còn cần cả thông tin kiểu dữ liệu.
- Thông tin kiểu chỉ có thể biết khi runtime, nên JIT compiler biên dịch mã ở runtime.
Những hiểu lầm về mối quan hệ giữa compiler và interpreter
- Nếu đã có compiler thì không cần interpreter?
- Với C/C++, interpreter không quá hữu ích, nhưng với những trường hợp như WebAssembly, interpreter có thể mang lại lợi ích về tính dễ phát triển và sử dụng, khả năng debug, bảo mật, v.v.
Những hiểu lầm về các giai đoạn trung gian của compiler
- Middle-end độc lập với target/platform?
- Với LLVM, middle-end không hoàn toàn độc lập với target/platform.
Những hiểu lầm về tối ưu hóa data locality
- Compiler tối ưu data locality?
- Compiler tối ưu tính cục bộ của instruction cache, nhưng gần như không tối ưu data locality.
- Tối ưu data locality đòi hỏi thay đổi lớn đối với mã, và compiler C/C++ không thể thực hiện các thay đổi như vậy.
- Để cải thiện data locality, nên dùng các kỹ thuật như thiết kế hướng dữ liệu.
Những hiểu lầm về tốc độ biên dịch
-O0cho tốc độ biên dịch nhanh?-O0tạo ra mã dễ debug và dễ dự đoán, nhưng không phải lúc nào cũng đảm bảo biên dịch nhanh.- Nói chung
-O0nhanh hơn-O2, nhưng còn tùy quy mô dự án và compiler. - Để biên dịch nhanh, có thể cân nhắc bỏ qua pipeline biên dịch tiêu chuẩn (ví dụ: TinyCC), hoặc tạo trực tiếp LLVM IR.
Những hiểu lầm về tốc độ biên dịch template
- Template làm biên dịch chậm?
- C++ template biên dịch chậm là do mô hình biên dịch của C++, không phải do bản thân template.
- Bản thân template không làm tốc độ biên dịch giảm mạnh.
- Thư viện chuẩn Phobos của Dlang dùng rất nhiều template nhưng vẫn biên dịch nhanh.
Những hiểu lầm về giá trị của biên dịch riêng lẻ
- Biên dịch riêng lẻ luôn đáng giá?
- Biên dịch riêng lẻ có thể khiến thời gian liên kết kéo dài.
- Với nhiều dự án, unity build (đưa toàn bộ mã vào một file duy nhất) cho hiệu năng tốt hơn.
- Unity build mang lại lợi ích như tối ưu toàn chương trình, tăng tốc độ biên dịch và cải thiện log lỗi.
- Trường hợp biên dịch riêng lẻ tốt hơn unity build là khá hiếm.
Những hiểu lầm về Link Time Optimization (LTO)
- Vì sao Link Time Optimization (LTO) lại diễn ra ở thời điểm liên kết?
- LTO được thực hiện để tối ưu toàn bộ chương trình.
- Về mặt lý thuyết, thực hiện tối ưu toàn chương trình ở middle-end sẽ hợp lý hơn, nhưng do các vấn đề thực tế của hệ thống build C/C++ (khó tìm source file và xác định quan hệ gọi hàm), nên việc này được thực hiện ở thời điểm liên kết.
- Vì linker có thể tìm thấy mọi object file, compiler sẽ đưa vào object file một biểu diễn ngôn ngữ trung gian như LLVM IR để linker có thể truy cập.
Những hiểu lầm về tối ưu hóa inlining
- Inlining hữu ích chủ yếu vì loại bỏ lệnh gọi hàm?
- Việc loại bỏ lệnh gọi hàm là một lợi ích, nhưng lợi ích lớn nhất của inlining là mở đường cho các tối ưu hóa khác.
- Inlining cho phép tối ưu hóa liên hàm.
- Khi mã của nhiều hàm được gộp vào một hàm nhờ inlining, có thể áp dụng các kỹ thuật tối ưu hóa nội hàm vốn đã có.
Những hiểu lầm về vai trò của từ khóa inline
- Từ khóa inline có liên quan đến tối ưu hóa inlining không?
- Trong C++, từ khóa
inlineban đầu được dùng như một gợi ý cho optimizer, nhưng từ sau C++98, nó mang nghĩa “cho phép nhiều định nghĩa”. - Với LLVM, nếu có từ khóa
inlinethì thuộc tínhinlinehintsẽ được thêm vào và ngưỡng inlining được nâng lên, nhưng tác động không lớn. - Nếu muốn một hàm luôn được inline, cần dùng chỉ định
always_inline.
- Trong C++, từ khóa
Những hiểu lầm về tài liệu học compiler
- LLVM là compiler tốt nhất để học?
- LLVM có giá trị về mặt giáo dục, nhưng vì hỗ trợ nhiều use case nên rất phức tạp và đồ sộ.
- Để học phát triển compiler, nên xem qua trước các compiler nhỏ và đơn giản hơn như Go compiler, LDC, DMD.
Những hiểu lầm về Undefined Behavior
-
Undefined Behavior chỉ giúp tối ưu hóa tốt hơn?
- Undefined Behavior cũng có thể làm vô hiệu hóa tối ưu hóa.
-
Compiler có thể “đơn giản” định nghĩa Undefined Behavior?
- Compiler có thể định nghĩa Undefined Behavior, nhưng điều đó có thể ảnh hưởng đến hiệu năng.
- Sẽ là lý tưởng nếu compiler định nghĩa mọi Undefined Behavior theo hành vi của nền tảng, nhưng trên thực tế điều đó không hề dễ.
Những hiểu lầm về sinh mã dựa trên AI
- Sinh mã với độ chính xác 99% là chấp nhận được?
- Độ chính xác 99% của mã do compiler tạo ra thực tế rất khó dùng.
- 1% lỗi trong mã sẽ gây ra khó khăn lớn cho việc debug và bảo trì.
- Trong các dự án quy mô lớn, 1% lỗi có thể dẫn đến những vấn đề cực kỳ nghiêm trọng.
- Hiện tại, LLM chậm hơn compiler rất nhiều, nên không phù hợp cho sinh mã trực tuyến.
Chưa có bình luận nào.