C ++ 템플릿을 사용하는 일반 및 메타 프로그래밍은 어느 정도까지 컴퓨팅 과학에 유용합니까?


17

C ++ 언어는 템플릿을 통한 일반적인 프로그래밍메타 프로그래밍 을 제공합니다 . 이러한 기술은 많은 대규모 과학 컴퓨팅 패키지 (예 : MPQC , LAMMPS , CGAL , Trilinos )에 적용되었습니다. 그러나 전체 개발 시간과 동일하거나 적절한 효율성에 대한 유용성 측면에서 C 또는 Fortran과 같은 비 제네릭, 비 메타 언어를 능가하는 과학적 컴퓨팅 가치에 실제로 기여한 것은 무엇입니까?

과학적인 컴퓨팅 작업이 주어지면 C ++ 템플릿을 통한 일반 및 메타 프로그래밍이 잘 이해 된 벤치 마크 (코드 라인, 사람 노력 등)로 측정 된 생산성, 표현성 또는 유용성 향상을 보여 줍니까? 이에 따라 일반 프로그래밍 및 메타 프로그래밍에 C ++ 템플릿을 사용하면 어떤 위험이 발생합니까?


나는이 질문이 의견에 너무 개방적 일 수 있다고 우려하지만, 공동체 사람들이 말하는 것을보고 싶다.
Geoff Oxberry

1
댓글 탈선을 완전히 삭제했습니다. 채팅이나 메타로 다시 게시하고 싶다면 기쁘다. 여기 내 메타를 참조 하십시오 .
Aron Ahmadia

3
또한 언제 사용하고 언제 표현식 템플릿을 피해야하는지 에 대한 조언은 관련 질문을 참조하십시오 .
Aron Ahmadia

LAMMPS가 템플릿이나 메타 프로그래밍을 사용한다고 말하는 것이 옳지 않다고 생각합니다. LAMMPS는 대부분 포트란처럼 보이는 객체 지향 코드입니다. MPQC가 템플릿을 많이 사용한다고 생각하지는 않지만 객체 지향적이고 다형성입니다.
Jeff

1
OpenFOAM 은 템플릿과 C ++의 다른 기능을 많이 사용합니다.
Dohn Joe

답변:


14

전반적으로 템플릿 메타 프로그래밍은 실제로는 사용할 수없는 것으로 밝혀졌습니다. 컴파일 속도가 너무 느리고 오류 메시지를 해독하는 것이 불가능합니다. 메타 프로그래밍을 사용할 때 초보자를위한 진입 장벽도 너무 높습니다.

물론 Trilinos, deal.II (나만의 라이브러리), DUNE 및 기타 여러 라이브러리에서 볼 수 있듯이 일반적인 프로그래밍은 완전히 다른 문제입니다. 다른 데이터 유형에서 작동하는 동일한 개념을 표현하는 것은 결코 쉬운 일이 아닙니다. 커뮤니티는 메타 프로그래밍 문제를 피할 수있는 범위 내에서 머무르는 한이를 크게 수용했습니다. 제네릭 프로그래밍은 명백한 성공이라고 생각합니다.

물론 이러한 주제 중 어느 것도 OOP에 즉시 연결되지 않습니다. 다시 말하지만, OOP는 과학 컴퓨팅 커뮤니티에서 보편적으로 수용하고 있습니다. 일반적인 프로그래밍보다는 그다지 논쟁의 주제는 아닙니다. 지난 15 년 동안 작성된 모든 성공적인 라이브러리 (C ++, C 또는 Fortran으로 작성된)는 OOP 기술을 사용합니다.


4
tmp는 초보 사용자에게는 어려울 수 있지만 종종 라이브러리 내부에서 잘 수행됩니다. 실제로 코드 양을 줄일 수있는 기술 중 하나이지만 실제로 수행중인 작업을 알아야합니다. 내가 믿지 않는다면 Eigen 또는 Elemental의 출처를 읽으십시오. 템플릿이 없으면 거의 불가능한 아름다운 코드입니다.
aterrel

5
물론 가치가있는 기술입니다. 그러나 유지 관리가 어렵고 외부 인터페이스에 노출되면 사용하기가 어려운 경우가 많습니다. 즉, TMP가 사람들이 처음에 기대했던 성공이 아닌 이유 중 하나는 컴파일러가 매우 좋아 졌다는 것입니다. TMP는 컴파일 타임에 많은 것들이 알려져 있으며 실제 코드에 상수로 전파 될 수 있다는 사실을 깨달았습니다. 그러나 컴파일러는 인라이닝, 함수 클로닝 등에 상당히 능숙 해 졌으므로 오늘날 "정상적인"프로그래밍을 통해 이점의 상당 부분을 얻을 수 있습니다.
Wolfgang Bangerth 2016 년

15

경험을 바탕으로 예를 들어 보겠습니다. 매일 사용하는 대부분의 라이브러리는 어떤 방식 으로든 OOP를 사용합니다. OOP는 많은 도메인에 필요한 복잡성을 숨길 수 있지만 성능에 실제로 도움이되는 메커니즘은 아닙니다. 일어날 수있는 일은 라이브러리가 객체 계층을 기반으로 특정 최적화를 사용할 수 있지만 대부분 사용자에게 복잡성을 숨기는 것입니다. 디자인 패턴을 찾아보십시오. 이러한 복잡성을 숨기는 데 자주 사용되는 메커니즘입니다.

PETSc를 예로 들어 보겠습니다. PETSc는 OOP의 인스펙터 / 실행자 모델을 사용합니다. 여기서 해당 알고리즘은 주어진 객체에서 사용 가능한 루틴을보고 루틴을 수행하기 위해 실행할 루틴을 선택합니다. 이를 통해 사용자는 우려 사항을 분리 할 수 ​​있습니다. 예를 들어 매트릭스 동작은 모든 종류의 차단 또는 최적화 된 루틴을 포함 할 수 있으며 수많은 반복 솔버에서 효과적으로 사용할 수 있습니다. 사용자에게 고유 한 데이터 유형 및 평가를 지정할 수있는 기능을 제공함으로써 몇 가지 중요한 루틴을 얻었으며 전체 라이브러리 기능을 계속 사용할 수 있습니다.

내가 줄 또 다른 예는 FEniCS와 deal.II입니다. 이 두 라이브러리는 OOP를 사용하여 많은 유한 요소법을 일반화합니다. 요소 유형, 요소 순서, 구적 표현 등의 모든 것에서 상호 교환이 가능합니다. 이 두 라이브러리는 일부 특수 목적의 구조화 된 FEM 코드보다 "느리게"있지만 사용자에게 알려지지 않은 FEM의 복잡성으로 인해 다양한 문제를 해결할 수 있습니다.

마지막 예제는 Elemental입니다. Elemental은 MPI 커뮤니케이터 및 데이터 위치를 매우 간단한 언어 구성으로 관리하는 데 어려움이있는 새로운 고밀도 선형 대수 라이브러리입니다. 결과적으로 FLAME 직렬 코드가있는 경우 데이터 유형을 변경하면 Elemental을 통해 병렬 코드를 가질 수도 있습니다. 더 흥미로운 것은 분포를 다른 것과 동일하게 설정하여 데이터 분포를 가지고 놀 수 있다는 것입니다.

OOP는 수동 롤 어셈블리와 경쟁하기위한 패러다임이 아니라 복잡성을 관리하는 방법으로 생각해야합니다. 또한 제대로 수행하지 않으면 많은 오버 헤드가 발생하므로 타이밍을 유지하고 사용하는 메커니즘을 업데이트해야합니다.


3

OOP과학 컴퓨팅에서 사용되는 언어 기능 은 코드를 더 잘 이해하고 사용하는 데 도움이되는보다 간단한 코드 설명입니다. 예를 들어, FFT루틴은 코드를 번거롭게 만드는 각 함수 호출에 대해 많은 수의 인수를 전달해야합니다.

사용하여 module또는 class호출시 필요한 것만 문 나머지 인자로 전달 될 수있는 문제 설정 (즉, 배열의 크기 및 계수)와 관련.

내 경험에 따르면 SUBROUTINE55 개의 인수 (in & out)로 전화를 걸 었으며 코드를 더 잘 만들기 위해 5로 줄였습니다.

그게 가치 야


3

나는 과학 컴퓨팅을위한 일반적인 프로그래밍과 메타 프로그래밍을 강력히지지합니다. 필자는 실제로 운동량을 얻고있는 Feel ++ (http://www.feelpp.org)라는 기술을 기반으로 Galerkin 메서드 용 무료 소프트웨어 C ++ 라이브러리를 개발 중입니다. 컴파일 시간이 느리거나 여전히 배후에서 일어나는 일을 이해하려는 경우 학습 곡선이 가파르다는 등의 어려움이 여전히 존재합니다. 그러나 이것은 매우 흥미롭고 마음이 부는 것입니다. 라이브러리 수준에서 수행되고 도메인 별 언어의 복잡성을 숨기면 매우 강력한 도구를 얻게됩니다. 우리는 우리가 사용할 수있는 광범위한 방법을 사용하고 비교할 수 있습니다. 과학적 컴퓨팅의 목적을 가르치는 데있어 이것은 대규모 응용 분야에서 연구 및 새로운 수치 분석법에 있어서도 훌륭합니다. 물론 우리는 그 일을하지만 지금까지는 좋은 일을 할 수 있습니다. 우리는 그것을 사용하는 엔지니어, 물리학 자 및 수학자를 가지고 있습니다 : 그들 대부분은 변형 공식화를 위해 언어를 사용합니다. 우리 물리학 자들이 조작하는 공식 중 일부를 살펴보면, 나는 그것들이 변형 공식을 설명하기 위해 높은 수준의 언어없이 "수작업으로"수행되는 것을보고 싶지 않습니다. 저는 개인적으로 이러한 "기술"또는 "패러다임"이 코드 크기에 큰 요소를 곱해야하는 과학 컴퓨팅 코드의 복잡성을 해결하는 데 필요하다고 생각합니다. C ++에서 메타 프로그래밍 지원을 개선 할 필요는 있지만, 특히 C ++ 11 이후로 이미 좋은 상태를 유지하고 있습니다.


2

귀하 의 질문과 관련된 http://arxiv.org/abs/1104.1729 용지를 찾을 수 있습니다 . 성능 관점에서 표현 템플릿 (과학 코드에 사용되는 템플릿 메타 프로그래밍의 특정 응용 프로그램)에 대해 설명합니다.


그 종이는 나를 미치게한다. 가장 빠른 일반 포트란을 MKL과 비교해보십시오. 수동 튜닝 어셈블리는 열망하는 것이 아니며, 매 나노초마다 중요하며 많은 사람들이 재사용 할 수 있습니다.
aterrel

@aterrel : 이것은 내가 궁금하게 생각하는 대조입니다. 개발의 마지막 단계로서 손 최적화를해야한다는 것을 알고 있다면, 마지막 단계 이전에 사용할 언어를 어떤 언어로 선택 하시겠습니까? 어떤 언어를 선택해야하는지에 대한 자료가 있습니까?
Deathbreath

9
@Deathbreath : 몇 가지 다른 스레드에서도 대답을 반복합니다. 대부분 코드에서 마지막 속도 비트를 조정하는 것은 매우 드 something니다. 그러나 항상 고급 알고리즘을 프로그래밍하십시오. 따라서 큰 일을 빨리 할 수있는 언어를 선택하십시오. 저수준 물건을 어떻게 든 포함시키는 방법이 항상 있지만, 선택한 프로그래밍 언어를 결정하는 것은 아닙니다.
Wolfgang Bangerth

0

템플릿은 런타임에 유형 / 도메인 검사를 제거하는 데 매우 유용합니다. 이들은 컴파일 타임에 처리 할 수 ​​있습니다. 이론적으로 C 또는 Fortran에서 동일한 유형의 구현에 비해 성능을 향상시킬 수 있습니다. 여기서 유형 검사는 런타임시에만 수행 할 수 있습니다. 검사는 소스 코드로 구현됩니다. 그러나 프리 컴파일러 옵션을 사용하여 C에서 동일한 결과를 얻을 수 있지만 템플리트와 달리 수동으로 수행해야합니다.

그러나 템플릿도 상당한 오버 헤드를 생성 할 수 있습니다. 그들은 종종 명령 캐시 사용에 영향을 줄 수있는 코드 팽창을 만들 수 있습니다. 또한 일반적인 접근 방식은 최적화 중에 컴파일러를 방해 할 수 있습니다. 일반적인 접근 방식을 사용할 때 코드 분석이 항상 쉬운 것은 아닙니다. 컴파일러 최적화를 포함하여 항상 자동화 문제입니다. 출력 코드가 캐시 친화적이지 않은 경우가 많습니다.

유형 / 도메인 검사의 이점은 확실히 더 안전하지만 성능 측면에서 볼 수있는 유일한 이점이며 일반적으로 인식 할 수 없습니다. 그러나 내가 말했듯이 전반적인 효과는 수행중인 작업에 따라 부정적 일 수 있습니다. 그렇기 때문에 심각한 병목 현상이있는 곳에서 코드를 수동으로 최적화하는 것이 더 나은 이유입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.