1 điểm bởi GN⁺ 19 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Một backend mới hỗ trợ sinh mã C++ được đề xuất cho trình biên dịch OCaml, nhằm khắc phục các giới hạn của backend C hiện có
  • Mã được chuyển đổi được viết theo phong cách hàm thuần túy, không dùng trạng thái khả biến hay thư viện chuẩn, và tái cài đặt một phần mô-đun List
  • Việc chạy cần trình biên dịch C++ (g++), đồng thời hỗ trợ các tùy chọn để bỏ giới hạn độ sâu template hoặc truyền đối số
  • Hiệu năng khác nhau tùy theo trình biên dịch; khi áp dụng thuật toán sàng dựa trên hàng đợi ưu tiên đã cải tiến thì tốc độ và hiệu quả bộ nhớ được nâng lên
  • Cộng đồng đánh giá đây là một thử nghiệm kết hợp ngôn ngữ hàm và template metaprogramming, đồng thời cũng nhắc đến khả năng mở rộng sang Rust

Đề xuất bổ sung backend C++

  • Một bản vá bổ sung backend C++ cho trình biên dịch OCaml (ocamlc) đã được đề xuất
    • Đây là phiên bản cải tiến từ backend C không tăng dần hiện đang được dùng trong runtime và FFI
    • Có thể chuyển mã OCaml sang C++ bằng lệnh ocamlc -incr-c primes.ml
  • Mã C++ được chuyển đổi được viết theo phong cách hàm thuần túy nên không hỗ trợ trạng thái khả biến
    • Vì vậy không thể dùng thư viện chuẩn; trong ví dụ, một phần mô-đun List được tái cài đặt theo kiểu hàm thuần túy
    • Đầu ra được biểu diễn bằng cấu trúc lồng nhau dạng Cons<hd, tl>, dùng cấu trúc riêng để tránh xung đột với toán tử :: của C++
  • Việc chạy cần trình biên dịch C++ (g++), và có thể truyền đối số bằng tùy chọn -Dlimit=100
    • Kết quả chạy được in ra dưới dạng thông báo lỗi của trình biên dịch
    • Với các phép tính lớn, có thể bỏ giới hạn độ sâu template bằng tùy chọn -ftemplate-depth=999999
  • Hiệu năng khác nhau tùy theo trình biên dịch
    • g++ mất khoảng 30 giây để tính số nguyên tố đến 10000, dùng 11GiB bộ nhớ
    • clang++ phát cảnh báo trong chưa đầy 1 giây rồi gặp lỗi phân đoạn
    • Khi áp dụng thuật toán sàng của O’Neill dựa trên hàng đợi ưu tiên, hiệu năng cải thiện còn 8 giây và 3.1GiB
  • Hướng mở rộng trong tương lai có nhắc đến hỗ trợ Rust
    • Có đề cập rằng khi Rust hoàn thiện impl specialization một phần, việc chạy chương trình OCaml có thể trở nên khả thi

Phản ứng và thảo luận của cộng đồng

  • Kiểm thử tính năng và phản hồi

    • redianthus hỏi liệu có hỗ trợ kiểu dữ liệu đệ quy không đồng nhất hay không
    • stedolan đã sửa lỗi do %predint chưa được hiện thực và xác nhận kiểu đó hoạt động bình thường
  • Hài hước và phản ứng

    • avsm đùa rằng: “Đang cần C-- mà lại là C++, vậy thỏa hiệp bằng C# đi”
    • stedolan đáp lại rằng: “Năm sau tôi sẽ thử số phức ℂ”
    • Nhiều phản ứng emoji như 😂, ❤️, 🚀 cho thấy cộng đồng đón nhận tích cực
  • Đề xuất kỹ thuật

    • AdelKS đưa ra một phương án thay thế dùng đánh giá constexpr thay vì template
      • Chia sẻ ví dụ mã tính số nguyên tố ở thời điểm biên dịch và nhúng trực tiếp vào tệp nhị phân
    • LoganDark trả lời một cách hài hước rằng: “Nhưng như thế thì không còn là niềm vui thuần túy nữa”, để giải thích lý do dùng template
  • Thảo luận thêm

    • redianthus nhận xét rằng: “Giờ thì C++ đã trở thành một ngôn ngữ hàm thực thụ”
      • Nhấn mạnh rằng có thể hiện thực các cấu trúc dữ liệu hàm thuần túy của OCaml trong C++
    • dzmitry-lahoda nhắc đến một dự án đã có thể chạy OCaml trên Rust là contextgeneric/cgp

Ví dụ hiệu năng và thực thi

  • Ví dụ cơ bản: chương trình tính số nguyên tố
    • ocamlc -incr-c primes.ml → tạo primes.cpp
    • Chạy g++ -Dlimit=100 primes.cpp sẽ in ra danh sách số nguyên tố
  • Cấu hình hiệu năng cao

    • g++ -ftemplate-depth=999999 -Dlimit=10000 primes.cpp
    • Mất khoảng 30 giây, dùng 11GiB bộ nhớ
  • Khi áp dụng thuật toán cải tiến

    • Hiệu năng tăng lên còn 8 giây, 3.1GiB

Kết luận

  • PR này là một thử nghiệm backend mới chuyển OCaml sang C++, cho thấy khả năng kết hợp giữa ngôn ngữ hàm và template metaprogramming
  • Cộng đồng đón nhận đây như một ví dụ kết hợp giữa hài hước kỹ thuật và thử nghiệm sáng tạo, đồng thời thảo luận rất sôi nổi
  • Khả năng mở rộng sang các ngôn ngữ khác như Rust cũng được nêu ra

1 bình luận

 
Ý kiến trên Hacker News
  • Nội dung thực sự rất tuyệt. Tôi muốn chia sẻ một mẹo khi viết mã C++ chạy lâu dài
    Kỳ lạ là trình thông dịch C++ hoàn toàn không có tail call optimization
    Vì vậy, phần lớn mã C++ theo phong cách thông dụng sẽ tự cài đặt trực tiếp các hàm như reverse, map, range, filter để tránh làm tràn stack
    Nếu triển khai theo cách này, người bảo trì sau này sẽ dễ làm việc hơn nhiều. Tốt hơn là dùng một cách tiếp cận có tính di động thay vì phụ thuộc vào cờ dòng lệnh

  • Tôi đã bật cười khi đọc câu “khi dùng những cấu trúc dữ liệu cao cấp như vậy, g++ có thể tính các số nguyên tố nhỏ hơn 10000 chỉ trong 8 giây, và chỉ dùng 3.1GiB bộ nhớ”
    Cuối cùng thì chiếc laptop của tôi cũng có thể tính số nguyên tố rồi

  • Tôi thực sự đồng cảm khi đọc đoạn “mã này được dịch sang C++ theo kiểu idiomatic và dễ đọc”
    Với tư cách là người yêu thích C++, tôi nghĩ đây đúng là mã C++ dễ đọc

    • Tôi đồng ý với phần lớn điều đó, nhưng đoạn như typedef I<((I<((n::val (p::val))>::val) != (I<0>::val))> res; thì đúng là mánh template ở cấp độ ma thuật
      Đây là lần đầu tôi thấy một biểu thức điều kiện được đưa vào bên trong định nghĩa kiểu trong C++
      Về sau tôi mới nhận ra đây không phải mã thực tế, mà là một phần của logic đánh giá template
      Tức là một phần logic trình biên dịch của ngôn ngữ bậc cao đã được đẩy sang engine template
      Cách tiếp cận này có thể còn hiệu quả hơn là dành thêm thời gian cho parser
      Vì thế giờ tôi đang nghĩ đến chuyện dùng C++ làm đích lowering cho framework trình biên dịch elevate mà tôi đang phát triển
  • Khi đọc câu “C++ is a purely functional language”, lúc đầu tôi tưởng đó là lỗi gõ nên đã nhướng mày
    Nhưng khi biết đó không phải lỗi gõ, tôi lại càng thấy thú vị hơn. Phần còn lại cũng rất tuyệt

  • Bài này đã làm ngày của tôi vui hơn. Cảm ơn

  • Stephen Dolan đúng là chưa bao giờ làm người ta thất vọng. Lần nào cũng khiến tôi ngạc nhiên

  • Khi đọc đoạn “C++ là một ngôn ngữ thuần hàm và không hỗ trợ trạng thái có thể thay đổi. Để chạy một chương trình C++, bạn cần một trình thông dịch C++”
    Trong khoảnh khắc tôi đã tưởng đó là trò đùa Cá tháng Tư. Dù tháng 4 đã qua rồi