>백엔드 개발 >파이썬 튜토리얼 >컴파일러 관점에서 Python 성능 최적화

컴파일러 관점에서 Python 성능 최적화

王林
王林앞으로
2023-04-15 11:46:05945검색

"인생은 짧다, 파이썬이 필요하다"!

베테랑 코더들은 Python의 우아함을 정말 좋아합니다. 그러나 프로덕션 환경에서는 성능을 최적화하도록 구축되지 않은 Python과 같은 동적 언어 기능은 위험할 수 있습니다. 따라서 TensorFlow 또는 PyTorch와 같은 인기 있는 고성능 라이브러리는 주로 Python을 사용합니다. 최적화된 C/C++ 라이브러리와 상호 작용하는 데 사용되는 인터페이스 언어입니다.

Python 프로그램의 성능을 최적화하는 방법은 여러 가지가 있습니다. 컴파일러 관점에서 보면 네이티브 기계 코드의 런타임 오버헤드를 낮추면서 C 또는 C++와 같은 낮은 수준의 정적으로 분석 가능한 언어로 고성능을 컴파일할 수 있습니다. 성능면에서 C/C++와 비교할 수 있습니다.

Codon은 사전 컴파일, 전문적인 양방향 유형 검사 및 새로운 양방향 중간 표현을 활용하여 언어 구문 및 컴파일러 최적화에서 선택적 도메인별 확장을 활성화하는 컴파일러로 볼 수 있습니다. 이를 통해 전문 프로그래머는 직관적이고 높은 수준이며 친숙한 방식으로 고성능 코드를 작성할 수 있습니다.

다른 성능 지향 Python 구현(예: PyPy 또는 Numba)과 달리 Codon은 기존 Python 런타임(예: CPython)을 사용하지 않고 처음부터 정적 실행 파일로 미리 컴파일된 독립형 시스템으로 구축되었습니다. 따라서 원칙적으로 Codon은 더 나은 성능을 달성하고 전역 인터프리터 잠금과 같은 Python 런타임 관련 문제를 극복할 수 있습니다. 실제로 Codon은 C 컴파일러와 같은 Python 스크립트를 기본 코드로 컴파일하여 해석된 실행보다 10~100배 빠르게 실행됩니다.

컴파일러 관점에서 Python 성능 최적화

1. Codon 소개

Codon은 생물정보학 DSL인 Seq 언어를 기반으로 모델링되었습니다. Seq는 원래 채택 용이성, 뛰어난 성능, 강력한 표현 기능 등 많은 장점을 갖춘 피라미드 스타일 DSL로 설계되었습니다. 그러나 엄격한 유형 규칙으로 인해 Seq는 많은 일반적인 Python 언어 구성을 지원하지 않으며 새로운 컴파일러 최적화를 쉽게 구현할 수 있는 메커니즘도 제공하지 않습니다. Codon은 양방향 IR과 향상된 유형 검사기를 적용하여 Seq를 기반으로 이러한 문제에 대한 일반적인 솔루션을 제공합니다.

Codon은 Python의 대부분의 기능을 다루고 특정 영역에서 최적화를 달성하기 위한 프레임워크를 제공합니다. 또한 다양한 언어 기능을 더 잘 처리할 수 있도록 유연한 유형 시스템이 제공됩니다. 유형 시스템은 RPython 및 PyPy 및 정적 유형 시스템과 유사합니다. 이러한 아이디어는 PRuby와 같은 다른 동적 언어의 맥락에서도 적용되었습니다. 양방향 IR에서 사용되는 접근 방식은 Java의 검사 프레임워크와 같은 포워드 플러그형 시스템과 유사합니다.

코돈의 Intermediate Expression은 최초의 커스터마이징 가능한 IR은 아니지만, 모든 콘텐츠의 커스터마이징을 지원하지는 않으며, 대신 양방향성과 결합하여 보다 복잡한 기능을 구현할 수 있는 간단하고 잘 정의된 커스터마이징을 선택합니다. 구조 측면에서 CIR은 LLVM과 Rust의 IR에서 영감을 받았습니다. 이러한 IR은 크게 단순화된 노드 세트 및 구조의 이점을 가지며, 이는 결과적으로 IR 채널 구현을 단순화합니다. 그러나 구조적으로 이러한 구현은 소스 코드를 근본적으로 재구성하여 변환을 수행하기 위해 리팩토링해야 하는 의미 정보를 제거합니다. 이러한 단점을 해결하기 위해 Taichi는 복잡성이 증가하는 대신 제어 흐름과 의미 정보를 유지하는 계층 구조를 채택합니다. 그러나 Codon과 달리 이러한 IR은 언어의 프런트엔드에 대해 대체로 불가지론적이므로 유형 정확성을 유지하고 새 코드를 생성하는 것이 다소 비실용적이거나 불가능합니다. 따라서 CIR은 소스 코드의 제어 흐름 노드와 완전히 축소된 내부 노드 하위 집합을 유지하면서 이러한 메서드의 단순화된 계층 구조를 활용합니다. 중요한 것은 양방향성으로 이 구조를 강화하여 새로운 IR을 쉽게 생성하고 조작할 수 있다는 것입니다.

컴파일러 관점에서 Python 성능 최적화

2. 유형 검사 및 추론

Codon은 Python end와 같은 동적 언어의 맥락에서 이전에 수행된 것과 유사하게 런타임 유형 정보를 사용하지 않고 정적 유형 검사를 활용하고 LLVM IR로 컴파일합니다. -to-end 유형 검사가 작동합니다. 이를 위해 Codon은 사용자가 유형에 수동으로 주석을 달 필요 없이 프로그램에서 유형을 추론하기 위해 HindleyMilner 스타일 추론을 활용하는 LTS-DI라는 정적 양방향 유형 시스템을 제공합니다. Python에서 지원됨 개발자들 사이에서는 일반적이지 않음).

Python의 구문 및 일반적인 Python 관용구의 특성으로 인해 LTS-DI는 표준 hm과 유사한 추론을 채택하여 이해력, 반복자, 생성기, 복잡한 함수 연산, 변수 매개변수, 정적 유형 검사 등과 같은 주목할만한 Python 구성을 지원합니다. 이러한 구조와 기타 여러 구조를 처리하기 위해 LTS-DI는 다음을 사용합니다.

  1. 단형성(각 입력 매개변수 조합에 대해 별도의 함수 버전 인스턴스화)
  2. 현지화(각 함수를 격리된 유형 검사 단위로 처리)
  3. 지연 인스턴스화(모든 함수 매개변수가 알려질 때까지 함수 인스턴스화가 지연됨) .

많은 Python 구문에는 코돈에서 지원하는 컴파일 타임 표현식(C++의 압축 pr 표현식과 유사)도 필요합니다. 이러한 접근 방식은 실제로는 드문 일이 아니며(예: C++ 템플릿은 싱글톤을 사용함), 지연 인스턴스화는 이미 HMF 유형 시스템에서 사용되지만, 유형 검사 Python 프로그램의 맥락에서 이들의 결합 사용을 인식하지 못합니다. 마지막으로, 현재 구현된 Codon의 유형 시스템은 완전히 정적이며 런타임 유형 추론을 수행하지 않습니다. 따라서 런타임 다형성 또는 런타임 반영과 같은 일부 Python 기능은 지원되지 않습니다. 과학 컴퓨팅의 맥락에서 이러한 기능을 제거하는 것은 유틸리티와 성능 간의 합리적인 균형을 나타내는 것으로 밝혀졌습니다.

3. 중간 표현식

많은 언어는 비교적 간단한 방식으로 컴파일됩니다. 소스 코드는 AST(추상 구문 트리)로 구문 분석되고 최적화되어 기계어 코드로 변환되며, 종종 LLVM과 같은 프레임워크의 도움을 받습니다. . 이 접근 방식은 상대적으로 구현하기 쉽지만 AST에는 특정 프로그램을 나타내는 데 필요한 것보다 더 많은 노드 유형이 포함되는 경우가 많습니다. 이러한 복잡성으로 인해 최적화, 변환 및 분석 구현이 어렵거나 심지어 비실용적일 수도 있습니다. 또 다른 접근 방식은 최적화 단계를 수행하기 전에 AST를 중간 표현(IR)으로 변환하는 것입니다. 중간 표현에는 일반적으로 잘 정의된 의미 체계를 갖춘 단순화된 노드 세트가 포함되어 있어 변환 및 최적화에 더 도움이 됩니다.

컴파일러 관점에서 Python 성능 최적화

Codon은 위 이미지에 표시된 것처럼 유형 검사와 최적화 단계 사이에 있는 IR에서 이 접근 방식을 구현합니다. CIR(Codon's Intermediate Representation)은 AST보다 훨씬 간단하며 구조가 더 간단하고 노드 유형도 더 적습니다. 단순함에도 불구하고 Codon의 중간 표현은 소스 코드의 의미 정보 대부분을 유지하고 "점진적 축소"를 촉진하여 여러 수준의 추상화에서 최적화를 가능하게 합니다.

3.1 소스 코드 매핑

CIR은 부분적으로 LLVM의 IR에서 영감을 받았습니다. LLVM에서는 SSA(Single Static Allocation) 형태와 유사한 구조를 채택하여 개념적으로 메모리 위치와 유사한 위치에 할당된 값과 변수를 구별하고, 먼저 소스코드가 선형적으로 진행된다. 중간 표현식을 생성하기 위해 유형 검사가 수행되는 추상 구문 트리로 구문 분석됩니다. 그러나 다른 컴파일 프레임워크와 달리 Codon은 양방향이며 IR 최적화는 유형 검사 단계로 돌아가 원래 프로그램에 없었던 새로운 노드를 생성할 수 있습니다. 프레임워크는 "도메인 확장 가능"하며 "DSL 플러그인"은 라이브러리 모듈, 구문 및 도메인별 최적화로 구성됩니다.

소스 코드 구조 매핑을 달성하기 위해 값을 임의로 큰 트리에 중첩할 수 있습니다. 예를 들어 이 구조를 사용하면 CIR을 제어 흐름 그래프로 쉽게 줄일 수 있습니다. 그러나 LLVM과 달리 CIR은 원래 제어 흐름을 나타내기 위해 스트림이라는 명시적 노드를 사용하여 소스 코드와 긴밀한 구조적 대응을 허용했습니다. 제어 흐름 계층 구조를 명시적으로 표현하는 것은 Taichi가 취한 접근 방식과 유사합니다. 중요한 것은 이를 통해 제어 흐름의 정확한 개념에 의존하는 최적화 및 변환을 더 쉽게 구현할 수 있다는 것입니다. 간단한 예는 CIR에서 명시적인 루프를 유지하고 LLVM IR에서처럼 분기의 미로를 해독하는 대신 코돈이 루프의 일반적인 패턴을 쉽게 식별할 수 있도록 하는 스트림입니다.

3.2 연산자

CIR은 "+"와 같은 연산자를 명시적으로 나타내지 않지만 이를 해당 함수 호출로 변환합니다. 이를 통해 Python과 동일한 의미로 모든 유형의 원활한 연산자 오버로드가 가능합니다. 예를 들어 + 연산자는 추가 호출로 확인됩니다.

이 접근 방식에서 발생하는 자연스러운 질문은 int 및 float와 같은 기본 유형에 대한 연산자를 구현하는 방법입니다. Codon은 @llvm 함수 주석을 통해 인라인 LLVM IR을 허용하여 이 문제를 해결합니다. 이를 통해 모든 기본 연산자를 코돈 소스 코드로 작성할 수 있습니다. 교환성, 결합성 등 연산자 속성에 대한 정보는 IR의 주석으로 전달될 수 있습니다.

3.3 양방향 IR

기존 컴파일 파이프라인은 데이터 흐름이 선형입니다. 소스 코드는 AST로 구문 분석되고 일반적으로 IR로 변환되고 최적화된 후 최종적으로 기계어 코드로 변환됩니다. Codon은 IR 채널이 유형 확인 단계로 돌아가서 소스 프로그램에 존재하지 않는 새로운 IR 노드와 특수 노드를 생성할 수 있는 양방향 IR 개념을 도입했습니다. 그 이점은 다음과 같습니다:

  • 대부분의 복잡한 변환은 코돈에서 직접 구현할 수 있습니다. 예를 들어, 프리페치 최적화에는 일반 동적 프로그램 스케줄러가 포함되는데, 이는 Codon IR에서만 구현하기에는 비현실적입니다.
  • 사용자 정의 데이터 유형의 새로운 인스턴스화는 요청 시 생성될 수 있습니다. 예를 들어 Codon 사전을 사용해야 하는 최적화는 적절한 키 및 값 유형에 대한 Dict 유형으로 인스턴스화될 수 있습니다. 유형이나 함수를 인스턴스화하는 것은 계단식 구현 및 전문화로 인해 유형 검사기를 완전히 다시 호출해야 하는 매우 간단한 프로세스입니다.

마찬가지로 IR 채널 자체는 Codon의 표현 유형 시스템을 사용하여 다양한 유형에 대해 작동하므로 일반적일 수 있습니다. IR 유형에는 AST 유형과 달리 연관된 제네릭이 없습니다. 그러나 각 CIR 유형은 이를 생성하는 데 사용된 AST 유형에 대한 참조와 AST 일반 유형 매개변수를 전달합니다. 이러한 연관된 ​​AST 유형은 유형 검사기를 다시 호출할 때 사용되며 기본 제네릭에 대해 CIR 유형을 쿼리할 수 있도록 합니다. CIR 유형은 상위 수준 추상화에 해당합니다. LLVM IR 유형은 더 낮으며 Codon 유형에 직접 매핑되지 않습니다.

실제로 CIR 전달 중에 새로운 유형을 인스턴스화하는 기능은 많은 CIR 작업에 매우 중요합니다. 예를 들어, 주어진 CIR 값 x 및 y에서 튜플 (x,y)를 생성하려면 새로운 튜플 유형 tuple[X,Y](여기서 대문자 식별자는 표현식 유형임)를 인스턴스화해야 하며, 이는 차례로 새로운 인스턴스화를 필요로 합니다. 등식 및 부등식 검사, 반복, 해싱 등을 위한 튜플 연산자. 그러나 유형 검사기를 다시 호출하면 이 과정이 원활해집니다.

컴파일러 관점에서 Python 성능 최적화

위 그림은 CIR 소스 코드 매핑에 대한 간단한 피보나치 함수의 예입니다. 함수 fib는 단일 정수 인수를 사용하여 CIR BodiedFunc에 매핑됩니다. 본문에는 상수를 반환하거나 결과를 얻기 위해 함수를 재귀적으로 호출하는 If 제어 흐름이 포함되어 있습니다. +와 같은 연산자는 함수 호출(예: add)로 변환되지만 IR은 구조의 원시 소스 코드에 매핑되어 간단한 패턴 일치 및 변환이 가능합니다. 이런 경우에는 단순히 Call 핸들러를 오버로드하고, 해당 함수가 교체 조건을 충족하는지 확인하고, 일치하면 해당 작업을 수행하면 됩니다. 사용자는 자신만의 순회 방식을 정의하고 IR 구조를 마음대로 수정할 수도 있습니다.

3.4 채널 및 변환

CIR은 포괄적인 분석 및 변환 인프라를 제공합니다. 사용자는 다양한 CIR 내장 애플리케이션 클래스를 사용하여 패스를 작성하고 비밀번호 관리자에 등록합니다. 여기서 더 복잡한 채널은 CIR의 양방향성을 활용하고 유형을 다시 호출할 수 있습니다. 새로운 CIR 유형, 기능 및 방법을 얻기 위한 검사기입니다. 그 예는 아래 그림에 나와 있습니다.

컴파일러 관점에서 Python 성능 최적화

이 예에서는 foo 함수에 대한 호출이 검색되고 각 호출 후에 foo의 매개변수와 해당 출력을 검증하는 호출이 삽입됩니다. 두 함수 모두 제네릭이므로 유형 검사기가 다시 호출되어 세 가지 새롭고 고유한 유효성 검사 인스턴스화를 생성합니다. 새로운 유형과 함수를 인스턴스화하려면 가능한 특수화를 처리하고 추가 노드를 구현해야 하며(예를 들어 검증을 구현하려면 예제에서 == 연산자 메서드 __eq__을 구현해야 함) 나중에 사용하기 위해 구현을 캐싱해야 합니다.

3.5 코드 생성 및 실행

Codon은 LLVM을 사용하여 네이티브 코드를 생성합니다. Codon IR에서 LLVM IR로의 변환은 일반적으로 간단한 과정입니다. 대부분의 Codon 유형은 LLVM IR 유형으로 직관적으로 변환될 수도 있습니다. int는 i64가 되고, float는 double이 되고, bool은 int8이 됩니다. 이러한 변환을 통해 C/C++ 상호 운용성도 허용됩니다. 튜플 유형은 값으로 전달되는 적절한 요소 유형을 포함하는 구조체 유형으로 변환됩니다(참고: 튜플은 Python에서 변경할 수 없습니다). 이러한 튜플 처리 방법을 사용하면 대부분의 경우 LLVM을 완전히 최적화할 수 있습니다. 목록, Dict 등과 같은 참조 유형은 동적으로 할당된 개체로 구현되며 참조로 전달됩니다. 이는 Python의 변수 의미 유형을 따르며 선택적인 유형이 전달되지 않도록 필요에 따라 선택적인 유형으로 업그레이드할 수 있습니다. LLVM의 i1 유형과 기본 유형의 튜플. 여기서 전자는 선택적 유형에 값이 포함되어 있는지 여부를 나타냅니다. 참조 유형에 대한 옵션은 Null 포인터를 사용하여 누락된 값을 나타내도록 특별히 설계되었습니다.

Generator는 Python에서 널리 사용되는 언어 구조입니다. 실제로 모든 for 루프는 생성기를 반복합니다. 중요한 점은 Codon의 생성기가 추가 오버헤드를 수행하지 않으며 가능할 때마다 동등한 표준 C 코드로 컴파일한다는 것입니다. 이를 위해 Codon은 LLVM 코루틴을 사용하여 생성기를 구현합니다.

Codon은 코드를 실행할 때 작은 런타임 라이브러리를 사용합니다. 특히 Boehm 가비지 컬렉터는 할당된 메모리를 관리하는 데 사용됩니다. Codon은 디버그와 릴리스라는 두 가지 컴파일 모드를 제공합니다. 디버그 모드에는 전체 디버그 정보가 포함되어 있어 GDB 및 LLDB와 같은 도구를 사용하여 프로그램을 디버깅할 수 있을 뿐만 아니라 파일 이름 및 줄 번호를 포함한 전체 역추적 정보도 포함됩니다. 릴리스 모드는 더 많은 최적화(GCC/Clang의 -O3 최적화 포함)를 수행하고 일부 보안 및 디버깅 정보를 생략합니다. 따라서 사용자는 빠른 프로그래밍 및 디버깅 주기를 위해 디버그 모드를 사용하고 고성능 배포를 위해 릴리스 모드를 사용할 수 있습니다.

3.6 확장성

프레임워크의 유연성과 양방향 IR, Python 구문의 전반적인 표현성으로 인해 Codon 애플리케이션은 일반적으로 소스 코드 자체에서 도메인별 구성 요소의 기능 대부분을 구현합니다. 모듈식 접근 방식은 동적 라이브러리 및 Codon 소스 파일로 패키지될 수 있습니다. 이 플러그인은 컴파일 타임에 코돈 컴파일러에 의해 로드될 수 있습니다.

MLIR과 같은 일부 프레임워크에서는 사용자 정의가 가능합니다. 반면 Condon IR은 일부 유형의 노드를 제한하고 유연성을 높이기 위해 양방향성에 의존합니다. 특히 CIR을 사용하면 사용자는 선언적 인터페이스를 통해 프레임워크의 나머지 부분과 상호 작용하는 "사용자 정의" 유형, 스트림, 상수 및 지시문에서 파생될 수 있습니다. 예를 들어, 사용자 정의 노드는 적절한 사용자 정의 기본 클래스(사용자 정의 유형, 사용자 정의 스트림 등)에서 제공되며 해당 LLVM IR을 구성하기 위해 "빌더"를 노출합니다. 사용자 정의 유형 및 노드를 구현하려면 가상 메소드를 통해 생성기(예: 건물 유형)를 정의해야 합니다. 사용자 정의 유형 클래스 자체는 이 생성기의 인스턴스를 얻기 위해 getBuilder 메소드를 정의합니다. 이 표준화된 노드 구성은 기존 채널 및 분석과 원활하게 작동합니다.

4 애플리케이션

4.1 벤치마크 성능

많은 표준 Python 프로그램이 이미 기본적으로 작동하므로 사전 업데이트(대신 단일 조회를 사용하도록 최적화할 수 있음)와 같은 Python 코드의 여러 공통 패턴을 쉽게 최적화할 수 있습니다. two ) 또는 연속적인 문자열 추가(할당 오버헤드를 줄이기 위해 단일 연결로 축소될 수 있음).

컴파일러 관점에서 Python 성능 최적화

위 그래프는 벤치마크에서 CPython(v3.10) 및 PyPy(v7.3)의 성능과 함께 Codon의 런타임 성능을 보여줍니다. 외부 라이브러리. CPython 및 PyPy에 비해 Codon은 항상 더 빠르며 때로는 몇 배나 빠릅니다. 벤치마크는 성능을 나타내는 좋은 지표이기는 하지만 단점이 없는 것은 아니며 전체 내용을 알려주지 못하는 경우도 많습니다. Codon을 사용하면 사용자는 다양한 도메인에 대한 간단한 Python 코드를 작성하는 동시에 실제 애플리케이션 및 데이터 세트에서 고성능을 제공할 수 있습니다.

4.2 OpenMP: 작업 및 루프 병렬 처리

Codon은 기존 Python 런타임과 독립적으로 구축되었기 때문에 CPython 전역 인터프리터 잠금의 영향을 받지 않으며 따라서 멀티스레딩을 최대한 활용할 수 있습니다. 병렬 프로그래밍을 지원하기 위해 Codon 확장을 통해 최종 사용자는 OpenMP를 사용할 수 있습니다.

OpenMP의 경우 병렬 루프의 본문은 새로운 함수로 설명되며 OpenMP 런타임에 의해 여러 스레드에 의해 호출됩니다. 예를 들어, 아래 그림의 루프 본문은 변수 a, b, c 및 루프 변수 i를 매개변수로 사용하는 함수 f로 설명됩니다.

컴파일러 관점에서 Python 성능 최적화

f에 대한 호출은 블록 크기가 10인 OpenMP의 동적 라운드 로빈 스케줄링 루틴을 호출하는 새로운 함수 g에 삽입됩니다. 마지막으로 대기열의 모든 스레드는 OpenMP의 fork_call 함수를 통해 g를 호출합니다. 결과는 위 이미지의 올바른 코드 조각에 표시되어 있으며, 개인 변수와 공유 변수를 처리하는 데 특별한 주의를 기울였습니다. 또한 변수를 줄이려면 원자성 작업(또는 잠금 사용)을 위한 추가 코드 생성과 OpenMP API 호출의 추가 계층이 필요합니다.

Codon의 양방향 컴파일은 OpenMP 패스의 핵심 구성 요소입니다. 다양한 루프에 대한 "템플릿"은 Codon 소스 코드에서 구현됩니다. 코드 분석 후 이러한 "템플릿"은 루프 본문, 블록 크기 및 일정을 채우고 공유 변수에 의존하는 표현식을 다시 작성하여 전달되고 전문화됩니다. 이 디자인은 패스 구현을 크게 단순화하고 어느 정도 다양성을 추가합니다.

Clang이나 GCC와 달리 Codon의 OpenMP 채널은 어떤 변수가 공유되고 어떤 변수가 비공개인지, 그리고 발생하는 축소된 코드를 추론할 수 있습니다. 축소 유형에 적절한 원자 매직 메소드(예: .aborom_add)를 제공하여 사용자 정의 축소를 간단히 수행할 수 있습니다. Codon은 생성기(Python 루프의 기본 동작)를 통해 "명령형 루프", 즉 시작, 중지 및 단계 값이 있는 C 스타일 루프로 반복됩니다. @par 태그가 있으면 강제 루프가 OpenMP 병렬 루프로 변환됩니다. 강제되지 않은 병렬 루프는 각 루프 반복마다 새 OpenMP 작업을 생성하고 루프 뒤에 동기화 지점을 배치하여 병렬화됩니다. 이 체계를 사용하면 모든 Python for-loop를 병렬화할 수 있습니다.

OpenMP 변환은 @par 속성으로 표시된 for 루프와 일치하는 CIR 세트로 구현되며 이러한 루프는 CIR에서 적절한 OpenMP 구성으로 변환됩니다. 거의 모든 OpenMP 구조는 Condon 자체의 고차 기능으로 구현됩니다.

4.3 CoLa: 블록 기반 압축을 위한 DSL

CoLa는 오늘날 사용되는 많은 일반적인 이미지 및 비디오 압축 알고리즘의 핵심인 블록 기반 데이터 압축을 대상으로 하는 Codon 기반 DSL입니다. 이러한 유형의 압축은 픽셀 영역을 일련의 더 작은 블록으로 분할하는 데 크게 의존하여 각 블록이 다른 블록에 대한 상대적인 위치를 알아야 하는 다차원 데이터 계층 구조를 형성합니다. 예를 들어, H.264 비디오 압축은 입력 프레임을 일련의 16x16 픽셀 블록으로 나누고 각 픽셀을 8x8 픽셀 블록으로 나눈 다음 이러한 픽셀을 4x4 픽셀 블록으로 나눕니다. 이러한 개별 픽셀 패치 사이의 위치를 ​​추적하려면 많은 양의 정보 데이터가 필요하며, 이로 인해 기존 구현의 기본 알고리즘이 빠르게 모호해집니다.

컴파일러 관점에서 Python 성능 최적화

CoLa는 계층적 데이터의 표현과 사용을 단순화하는 HMDA(Hierarchical MultiDimensional Array) 추상화를 도입합니다. HMDA는 일부 전역 좌표계를 기준으로 특정 HMDA의 원점을 추적하는 위치 개념이 포함된 다차원 배열을 나타냅니다. HMDA는 크기와 보폭도 추적할 수 있습니다. 이 세 가지 데이터를 사용하면 모든 HMDA는 프로그램의 어느 지점에서나 다른 HMDA를 ​​기준으로 자신의 위치를 ​​결정할 수 있습니다. CoLa는 Codon의 HMDA를 ​​블록과 뷰라는 두 가지 새로운 데이터 유형을 중심으로 한 라이브러리로 추상화합니다. 블록은 기본 다차원 배열을 생성하고 소유하며 뷰는 블록의 특정 영역을 가리킵니다. CoLa는 각각 블록과 뷰를 생성하는 구성 작업, 위치 복사 및 파티셔닝이라는 두 가지 주요 계층을 노출합니다. CoLa는 정수 및 슬라이스 인덱스를 사용하여 표준 인덱싱을 지원하지만 압축 표준이 데이터 액세스를 설명하는 방식을 에뮬레이션하는 두 가지 고유한 인덱싱 방식도 도입합니다. "Out-of-bounds" 인덱스를 사용하면 사용자가 뷰 주변의 데이터에 액세스할 수 있는 반면, "관리형" 인덱스를 사용하면 사용자는 다른 HMDA를 ​​사용하여 하나의 HMDA를 ​​인덱싱할 수 있습니다.

Codon의 물리학과 CoLa의 추상화의 결합은 사용자에게 고급 언어 및 압축 관련 추상화의 이점을 제공하는 반면, HMDA 추상화는 필요한 추가 인덱싱 작업으로 인해 상당한 런타임 오버헤드를 발생시킵니다. 압축의 경우 많은 HMDA 액세스가 계산의 가장 내부 수준에서 발생하므로 원래 배열에 액세스하는 것 외에 추가적인 계산은 런타임에 해로운 것으로 판명됩니다. CoLa는 Codon 프레임워크를 활용하여 계층 구조를 구현하고, 생성된 중간 보기 수를 줄이고, 특정 HMDA의 위치를 ​​추론하기 위한 전파 시도를 줄입니다. 이렇게 하면 계층 구조의 전체 크기가 줄어들고 실제 지수 계산이 단순화됩니다. 이러한 최적화가 없으면 CoLa는 JPEG 및 H.264에 대한 참조 C 코드보다 평균 48.8×, 6.7× 및 20.5× 느립니다. 최적화 후 동일한 참조 코드에 비해 평균 실행 시간이 각각 1.06×, 0.67× 및 0.91×로 성능이 크게 향상되었습니다.

CoLa는 Codon 플러그인으로 구현되므로 압축 프리미티브 라이브러리는 물론 생성 및 액세스 루틴을 최적화하는 CIR 및 LLVM 채널 세트도 함께 제공됩니다. CoLa는 또한 Codon에서 제공하는 사용자 정의 데이터 구조 액세스 구문과 연산자를 사용하여 일반적인 인덱싱 및 축소 작업을 단순화합니다.

5. 요약

본질적으로 codon은 DSL을 설계하고 빠르게 구현하기 위한 도메인 구성 가능 프레임워크입니다. 특화된 유형 검사 알고리즘과 새로운 양방향 IR 알고리즘을 적용하여 다양한 영역의 동적 코드를 쉽게 최적화할 수 있습니다. Python을 직접 사용하는 것과 비교할 때 Codon은 높은 수준의 단순성을 희생하지 않고도 C/C++ 성능을 유지할 수 있습니다.

현재 Codon에는 주로 런타임 다형성, 런타임 반영 및 유형 작업(예: 동적 메서드 테이블 수정, 클래스 멤버의 동적 추가, 메타클래스 및 클래스 데코레이터)을 포함하여 지원되지 않는 여러 Python 기능이 있습니다. 표준 Python 라이브러리 범위. Codon으로 컴파일된 Python은 제한적인 솔루션으로 존재할 수 있지만 주목할 가치가 있습니다.

【참고 자료 및 관련 자료】

🎜

위 내용은 컴파일러 관점에서 Python 성능 최적화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 51cto.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제