Tại sao gán đơn tĩnh được ưa thích hơn kiểu chuyển tiếp trong nhiều trình biên dịch được sử dụng trong ngành?


15

Theo trang Wikipedia về phân công đơn tĩnh (SSA) , SSA được sử dụng bởi các dự án lớn và nổi tiếng như LLVM, GCC, MSVC, Mono, Dalvik, SpiderMonkey và V8 trong khi trang về các dự án sử dụng kiểu tiếp tục truyền (CPS) là một chút thiếu so sánh.

Tôi có khái niệm rằng CPS được các nhà biên dịch và phiên dịch viên ưa thích sử dụng các ngôn ngữ chức năng chủ yếu - đặc biệt, Haskell và Scheme dường như có khuynh hướng mạnh đối với phong cách CPS do những hạn chế về đột biến hoặc cần hỗ trợ tiếp tục hạng nhất (tôi đoán rằng Smalltalk cũng có thể cần điều này). Tài liệu chính mà tôi gặp phải sử dụng CPS dường như là những tài liệu chủ yếu hoạt động trên Scheme hoặc liên quan đến Scheme ở một khía cạnh nào đó.

Có bất kỳ lý do cụ thể tại sao SSA được sử dụng trong công nghiệp bên cạnh đà áp dụng? SSA và CPS có mối quan hệ chặt chẽ; điều đó có nghĩa là nó sẽ dễ dàng được nêu ra theo nghĩa khác, nhưng có lẽ việc trình bày thông tin sẽ kém gọn hơn hoặc kém hiệu quả hơn đối với CPS.


2
IIRC, tối ưu hóa truyền thống cho các ngôn ngữ bắt buộc được thiết kế trong thời kỳ phân tích dataflow truyền thống sang dạng SSA dễ dàng hơn so với CPS .. Đặc biệt, chuỗi sử dụng def-def và def-use có thể "đọc" trực tiếp đại diện SSA. Quán tính được tính cho một cái gì đó
Bút danh

Câu trả lời:


9

Tôi tưởng tượng nhiều người triển khai trình biên dịch cho các ngôn ngữ mệnh lệnh điển hình đơn giản là không quen thuộc với các kỹ thuật biên dịch dựa trên CPS và CPS. Trong cộng đồng lập trình chức năng, cả phần tổng hợp dựa trên CPS và CPS đều là những kỹ thuật rất nổi tiếng - phần sau từ công việc của Guy Steele. Tuy nhiên, ngay cả trong cộng đồng FP, hầu hết các trình biên dịch không sử dụng các kỹ thuật dựa trên CPS để biên dịch trừ khi chính ngôn ngữ này hỗ trợ các toán tử điều khiển như call/cc. Một cái gì đó giống như Mẫu thông thường hành chính (ANF) (đôi khi còn được gọi là Mẫu thông thường đơn nguyên có liên quan mật thiết vì những lý do sẽ trở nên rõ ràng) được sử dụng có mối quan hệ chặt chẽ hơn với SSA so với CPS .

Nếu tôi nhớ chính xác, biểu mẫu thông thường quản trị lấy tên của nó từ thực tế là việc biên dịch dựa trên CPS có thể dẫn đến các bản beta-redexes trong mã trung gian không tương ứng với bất cứ điều gì trong mã nguồn. Chúng được gọi là "redexes hành chính". Những thứ này có thể giảm vào thời gian biên dịch, nhưng có một số lượng lớn nghiên cứu về việc thực hiện một biến đổi CPS sẽ tạo ra mã mà không có các bản đỏ hành chính ở nơi đầu tiên. Mục tiêu sau đó là tạo ra sản lượng ở dạng bình thường trong đó tất cả các redexes "hành chính" đều giảm và đây là nguồn gốc của Mẫu thông thường hành chính. Không mất nhiều thời gian để nhận ra rằng sẽ không có nhiều lợi ích khi xem điều này như một (n tối ưu hóa của một) quá trình hai bước: chuyển đổi CPS, giảm các lỗi đỏ hành chính. Đặc biệt, hình thức hành chính bình thường trông khá giống phong cách đơn điệu như được thực hành (bằng tay) đáng chú ý nhất là ở Haskell. Biến đổi CPS có thể được hiểu là một chuyển đổi sang kiểu đơn âm khi bạn tình cờ sử dụng đơn vị CPS (vì vậy thực sự có nhiều cách để "chuyển đổi" sang kiểu đơn âm tương ứng với các lệnh đánh giá khác nhau). Tuy nhiên, nói chung, bạn có thể đang sử dụng một đơn nguyên khá khác biệt, và do đó, việc chuyển đổi sang kiểu đơn nguyên và do đó hình thức hành chính thông thường không thực sự liên quan đến CPS nói riêng.

Tuy nhiên, có một số lợi ích đối với CPS so với ANF. Cụ thể, có một số tối ưu hóa nhất định mà bạn có thể thực hiện trong CPS chỉ bằng các tối ưu hóa tiêu chuẩn, chẳng hạn như giảm beta, yêu cầu (dường như) các quy tắc đặc biệt cho ANF. Từ quan điểm đơn nguyên, các quy tắc này tương ứng với chuyển đổi đi lại. Kết quả cuối cùng là có một lý thuyết có thể giải thích những quy tắc nào cần được thêm vào và tại sao. Một bài báo gần đây đưa ra một mô tả (mới và) khá rõ ràng về điều này (từ góc độ logic) và phần công việc liên quan của nó phục vụ như một cuộc khảo sát ngắn gọn nhưng đàng hoàng về các tài liệu về các chủ đề tôi đề cập.

Vấn đề với CPS gắn liền với một trong những lợi ích chính của nó. Chuyển đổi CPS cho phép bạn thực hiện các toán tử điều khiển như thế nào call/cc, nhưng điều này có nghĩa là mọi lệnh gọi hàm không cục bộ trong mã trung gian CPS phải được coi là hiệu ứng điều khiển có khả năng thực hiện. Nếu ngôn ngữ của bạn bao gồm các toán tử điều khiển, thì điều này cũng đúng như vậy (mặc dù sau đó hầu hết các chức năng có thể không thực hiện bất kỳ shenanigans kiểm soát nào). Nếu ngôn ngữ của bạn không bao gồm các toán tử điều khiển, thì sẽ có những bất biến toàn cầu về việc sử dụng các phần tiếp theo không rõ ràng tại địa phương. Điều này có nghĩa là có những tối ưu hóa không có cơ sở để thực hiện trên mã CPS chung sẽ là âm thanh để thực hiện đối với việc sử dụng CPS có hành vi đặc biệt tốt này. Một cách biểu hiện này là trongsự thay đổi độ chính xác của dữ liệu và phân tích dòng điều khiển . (Chuyển đổi CPS theo một số cách, gây tổn thương cho những người khác, mặc dù các cách mà nó giúp chủ yếu là do trùng lặp chứ không phải do chính khía cạnh CPS.) 1 Tất nhiên, bạn có thể thêm các quy tắc và điều chỉnh các phân tích để bù đắp cho điều này (nghĩa là khai thác các bất biến toàn cầu), nhưng sau đó bạn đã đánh bại một phần một trong những lợi ích chính của việc biên dịch dựa trên CPS, đó là nhiều tối ưu hóa đặc biệt (dường như) đặc biệt trở thành trường hợp đặc biệt của tối ưu hóa mục đích chung (đặc biệt là giảm beta ).

Cuối cùng, trừ khi ngôn ngữ của bạn có các toán tử điều khiển, thường không có nhiều lý do để sử dụng sơ đồ biên dịch dựa trên CPS. Khi bạn bù đắp cho các vấn đề tôi đã đề cập ở trên, bạn thường loại bỏ các lợi ích của việc biên dịch dựa trên CPS và tạo ra thứ gì đó tương đương với việc không sử dụng CPS. Tại thời điểm đó, CPS chỉ tạo ra mã trung gian tìm kiếm phức tạp để không có nhiều lợi ích. Một đối số cho việc biên dịch dựa trên CPS từ năm 2007 đã giải quyết một số vấn đề này và đưa ra một số lợi ích khác bằng cách sử dụng một hình thức chuyển đổi CPS khác. Những điều mà giấy sẽ trả được bao phủ một phần bởi sự (2017) giấy tôi đã đề cập trước đó.

1 Không phải sự tương đương giữa SSA và CPS làm cho điều này ít nhiều không thể thực hiện được? Không. Một trong những điều đầu tiên mà bài báo giới thiệu trạng thái tương đương này là tính tương đương không hoạt động đối với mã CPS tùy ý , nhưng nó hoạt động đối với đầu ra của biến đổi CPS (mà chúng xác định) cho ngôn ngữ không có toán tử điều khiển.


2
Đã một lúc kể từ câu trả lời ban đầu nhưng tôi cảm thấy đủ tốt để cuối cùng chấp nhận câu trả lời vì tôi hiểu hơn 10% ...
CinchBlue

2

Tôi không phải là một chuyên gia biên dịch, vì vậy hãy nói những gì tôi nói với một hạt muối, tôi hy vọng rằng một chuyên gia biên dịch thực sự sẽ kêu vang. Tôi đã nói rằng:

  • Mã CPSed có xu hướng nhảy không cục bộ rất nhiều, làm hỏng địa phương bộ đệm, do đó hiệu suất.
  • CPS đòi hỏi bộ sưu tập rác đắt tiền hơn so với việc biên dịch thông thường, thường có thể lưu trữ rất nhiều thứ trên ngăn xếp (nhanh hơn để phân bổ và phân bổ).

Cả hai âm mưu để làm cho mã được biên dịch bởi CPS-Transform tương đối chậm.


2
Tôi nghĩ rằng bạn đang trộn mã nguồn được chuyển đổi CPS (hoặc chuyển đổi nguồn thành nguồn) với việc sử dụng CPS một ngôn ngữ trung gian . Giả sử ngôn ngữ đầu vào của bạn không hỗ trợ các hiệu ứng điều khiển như call/cc, ví dụ, các phần tiếp theo sẽ được sử dụng với kỷ luật ngăn xếp - sẽ không cần bộ thu gom rác và các phần tiếp theo sẽ tương ứng, ít nhiều, cho các cạnh của luồng điều khiển đồ thị sẽ không có bất kỳ bước nhảy bổ sung. Bạn không cần phải thực hiện các phần tiếp theo bằng cách sử dụng một số mục đích chung cho các hàm bậc cao hơn.
Derek Elkins rời SE

@DerekElkins Tôi không rõ OP đang hỏi về điều gì.
Martin Berger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.