많은 업계에서 사용되는 컴파일러에서 연속 전달 스타일보다 정적 단일 할당이 선호되는 이유는 무엇입니까?


16

SSA (Static-Single Assignment)Wikipedia 페이지에 따르면 SSA는 LLVM, GCC, MSVC, Mono, Dalvik, SpiderMonkey 및 V8과 같이 크고 잘 알려진 프로젝트에서 사용되는 반면 연속 전달 스타일을 사용 하는 프로젝트 페이지는 SSA를 사용합니다. (CPS) 는 비교가 약간 부족합니다.

필자는 CPS가 주로 기능적 언어를 구현하는 컴파일러와 인터프리터에 의해 선호된다는 개념을 가지고 있습니다. 특히 Haskell과 Scheme은 돌연변이에 대한 제한이나 일류 연속 지원의 필요성으로 인해 CPS 스타일에 대한 강한 경향이있는 것으로 보입니다 (추측 할 것입니다) 스몰 토크도 필요할 것입니다). CPS를 사용하는 필자가 접한 주요 문헌은 주로 Scheme에서 작업 중이거나 Scheme과 관련이있는 것으로 보입니다.

SSA가 채택 모멘텀 외에 산업에서 사용되는 특별한 이유가 있습니까? SSA와 CPS는 밀접한 관계가 있습니다. 즉, 다른 측면에서 쉽게 설명 할 수 있지만 CPS의 경우 정보 표현이 간결하거나 효율성이 떨어질 수 있습니다.


3
전통적인 데이터 흐름 분석 시대에 설계된 명령형 언어에 대한 전통적인 최적화 인 IIRC는 CPS보다 SSA 양식으로보다 쉽게 ​​전송됩니다. 특히 use-def 및 def-use 체인은 SSA 표현을 직접 "읽을 수 있습니다". 관성은 무언가를 계산합니다
가명

답변:


9

전형적인 명령형 언어에 대한 많은 컴파일러 구현자가 CPS 및 CPS 기반 컴파일 기술에 익숙하지 않다고 생각합니다. 함수형 프로그래밍 커뮤니티에서 CPS와 CPS 기반 컴파일은 Guy Steele의 후자 인 매우 잘 알려진 기술입니다. 그럼에도 불구하고 FP 커뮤니티에서도 언어 자체가와 같은 제어 연산자를 지원하지 않는 한 대부분의 컴파일러는 컴파일에 CPS 기반 기술을 사용하지 않습니다 call/cc. 더 비슷해 관리 정규형 (때로는이라고도 (ANF) 단항 정규형 밀접하게 명확하게 할 이유 관련)이있는 사용 CPS는보다 SSA에 더 엄격한 관계를 .

올바르게 기억한다면 관리 표준 형식은 CPS 기반 컴파일이 소스 코드의 어떤 것과도 일치하지 않는 중간 코드에서 베타-레 덱스로 이어질 수 있다는 사실에서 그 이름을 얻습니다. 이것을 "관리적 redexes"라고했습니다. 이것은 컴파일 타임에 줄어들 수 있지만, 처음에는 관리적 수정없이 코드를 출력하는 CPS 변환 수행에 대한 많은 연구가있었습니다. 그런 다음 목표는 모든 "관리"개정이 줄어든 일반 양식으로 출력물을 생성하는 것이 었으며 이것이 관리 일반 양식의 기원이었습니다. 이것을 CPS- 변형, 행정적 재조정을 줄이는 2 단계 프로세스로 볼 때 많은 이점이 없다는 것을 깨닫는 데 오래 걸리지 않았습니다. 특히, 행정 정규 형식은 Haskell에서 가장 눈에 띄는 (손으로) 수도원 스타일과 비슷합니다. CPS 변환은 CPS 모나드를 사용하는 모나 딕 스타일로의 변환으로 이해 될 수 있습니다 (따라서 서로 다른 평가 순서에 해당하는 모나 딕 스타일로 "변환"하는 방법은 여러 가지가 있습니다). 그러나 일반적으로 매우 다른 모나드를 사용할 수 있으므로 모나 딕 스타일로 변환하므로 관리 일반 형식은 실제로 CPS와 관련이 없습니다.

그럼에도 불구하고 CPS 대 ANF에는 몇 가지 이점이있었습니다. 특히 베타 감소와 같이 ANF에 대한 임시 규칙이 요구되는 표준 최적화만으로 CPS에서 수행 할 수있는 특정 최적화가있었습니다. 모나 딕 관점에서이 규칙은 통근 변환에 해당합니다. 결론은 이제 어떤 규칙을 추가해야하며 그 이유를 설명 할 수있는 이론이 있습니다. 최근 논문 (논리적 관점에서)이의 (새로운) 꽤 명확한 설명을 제공하고 관련 작업 섹션은 내가 언급 주제에 대한 문헌에 짧지 만의 품위 조사 및 참조 역할을합니다.

CPS의 문제는 주요 이점 중 하나와 관련이 있습니다. CPS 변환을 사용하면과 같은 제어 연산자를 구현할 수 call/cc있지만 이는 CPS 중간 코드의 모든 로컬이 아닌 함수 호출이 잠재적으로 제어 효과를 수행하는 것으로 처리되어야 함을 의미합니다. 귀하의 언어에 제어 연산자가 포함되어 있다면, 이는 그대로 있어야합니다 (그러나 대부분의 함수는 제어 제어를 수행하지 않을 수도 있습니다). 귀하의 언어에 제어 연산자 포함되어 있지 않은 경우 , 지역에서 알 수없는 연속 사용에 대한 글로벌 불변이 있습니다. 즉, CPS를 특히 잘 사용하면 일반적인 CPS 코드에서 수행하기에 부적합한 최적화가 있습니다. 이것이 나타나는 한 가지 방법은데이터 및 제어 흐름 분석의 정확성 변화 . (CPS 변환은 어떤 방식 으로든 도움이되고 다른 방법으로도 아프지 만 도움이되는 방식은 대부분 CPS 측면이 아니라 복제 때문입니다.) 1 물론,이를 보완하기 위해 규칙을 추가하고 분석을 조정할 수 있습니다 (예 : 악용). CPS 기반 컴파일의 주요 이점 중 하나를 부분적으로 물리 쳤습니다. 이는 많은 것으로 보이는 특수 목적 애드혹 최적화가 범용 최적화 (특히 베타 감소)의 특수 사례가됩니다. ).

궁극적으로, 언어에 제어 연산자가 없으면 CPS 기반 컴파일 체계를 사용할 이유가별로 없습니다. 위에서 언급 한 문제에 대해 보상을 받으면 일반적으로 CPS 기반 컴파일의 이점을 제거하고 CPS를 사용하지 않는 것과 동등한 것을 생성했습니다. 이 시점에서 CPS는 복잡한 코드를 중간 코드로 만들어 많은 이점을 얻지 못했습니다. 2007 년 CPS 기반 컴파일에 대한 논쟁 은 이러한 문제 중 일부를 해결하고 다른 형태의 CPS 변환을 사용하여 다른 이점을 제공합니다. 종이가 자란 것은 앞서 언급 한 (2017) 종이에 의해 부분적으로 다루어 집니다.

1 SSA와 CPS의 동등성이 이것이 다소 불가능하지 않습니까? 제 첫번째 것의 한 이 등가 도입 용지 상태는 동등한 않는다는 것이다 하지 작동 임의 CPS 코드 그러나 그것은 언어 (그들이 정의하는) 변환 CPS의 출력 작업을 수행 하지 않고 제어 연산자.


2
최초의 답변 이후로 잠시 시간이
지났지

2

나는 컴파일러 전문가가 아니므로 소금 한알로 말한 것을 가져 가라. 진정한 컴파일러 전문가가 들어 오길 바란다.

  • CPS 코드는 로컬에서 많이 점프하지 않는 경향이 있으며, 이는 캐시 로컬 성을 손상시켜 성능을 저하시킵니다.
  • CPS는 일반적으로 스택에 많은 항목을 저장할 수있는 (일반적으로 할당 및 할당 해제가 더 빠름) 기존 컴파일보다 더 비싼 가비지 수집이 필요합니다.

둘 다 CPS 변환으로 컴파일 된 코드를 비교적 느리게 만드는 데 공모합니다.


3
CPS 변환 소스 코드 (또는 소스 간 변환)를 CPS 중간 언어 를 사용하여 혼합한다고 생각합니다 . 입력 언어가와 같은 제어 효과를 지원하지 않는 call/cc경우, 예를 들어 연속은 스택 규칙과 함께 사용됩니다. 가비지 수집기가 필요하지 않으며 연속은 제어 흐름의 가장자리에 해당합니다. 추가 점프가 발생하지 않도록 그래프. 고차 함수의 일부 범용 구현을 사용하여 연속을 구현할 필요는 없습니다.
Derek Elkins

@DerekElkins OP가 무엇을 요구했는지는 분명하지 않았습니다.
Martin Berger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.