계산 과학자가 std :: complex의 자체 버전을 구현해야하는 이유는 무엇입니까?


14

Eigen , Trilinosdeal.II 와 같은 계산 과학에서 잘 알려진 C ++ 라이브러리 std::complex<>는 복잡한 부동 소수점 숫자를 나타내는 표준 C ++ 템플릿 헤더 라이브러리 객체를 사용 합니다.

기본 생성자에 대한 질문에 대한 Jack Poulson의 답변 에서 그는 "여러 가지 이유로" Elementalstd::complex 에서 자신의 구현을 가지고 있다고 지적합니다 . 그 이유는 무엇입니까? 이 방법의 장점과 단점은 무엇입니까?

답변:


16

이 토론은 PETSc 목록에 여러 번 등장했다고 생각합니다. 나의 주요 이유는 다음과 같습니다.

  1. C ++ 표준에 따르면 std :: complex는 float, double 및 long double 데이터 유형에 대해서만 정의됩니다. 따라서 쿼드 정밀도와 같은 다른 데이터 유형에는 사용할 수 없습니다.

  2. 표준은 복소수 산술의 안정성을 보장하지 않습니다.

  3. 표준은 std :: complex의 데이터가 실제 구성 요소로 저장되고 그 뒤에 가상 구성 요소가 저장된다는 것을 보증하지 않습니다. 이것은 BLAS 및 LAPACK과 같은 외부 라이브러리와의 인터페이스에 중요합니다. 모든 주요 구현에 해당되지만 보장 할 수 있기를 바랍니다.

  4. 나는 실제와 가상의 구성 요소를 직접 조작 할 수있는 것을 선호합니다. std :: complex는이를 불필요하게 어렵게 만듭니다.

  5. 결국 데이터 유형이 필드를 요구하는 대신 링이어야하는보다 일반적인 버전을 원합니다. 여기에는 가우스 정수가 포함됩니다.


6
포인트 3은 C ++ 11에서 해결되었습니다. 그 경우 26.4.4 미국 z형의 좌변 표현 CV std::complex<T> 후는 reinterpret_cast<cv T(&)[2]>(z)reinterpret_cast<cv T(&)[2]>(z)[0]의 실수 부를 지정한다 zreinterpret_cast<cv T(&)[2]>(z)[1]허수 부분을 지정한다 z. 복소수 배열도 다룹니다.
James Custer

3
@JamesCuster : 결국 C ++ 11로 전환하는 것이 전부이지만, 반 이국적 아키텍처로 이식성을 유지하려는 과학 코드는 적어도 2-3 년 더 기다려야 할 것입니다. 또한 C ++ 11은 불행히도 문제의 일부만 해결합니다.
Jack Poulson

나는 누군가가 나중에이 질문을 볼 때를 대비하여 그것을 버리고 있다고 이해합니다.
James Custer

2
글쎄, 컴파일러가 C ++ 11을 지원할 때까지 기다려야한다고 말하는 것이 유행이라고 생각합니다. 모든 기존 구현이 이미이를 지원하므로 명시 적 요구 사항이 새로운 표준에 포함되었습니다. 다른 방법으로 std :: complex를 구현하는 것이 의미가 없기 때문에 기존 컴파일러 / 라이브러리 에서이 특정 레이아웃을 이미 가정하는 것이 안전하지 않은 경우는 생각할 수 없습니다.
Wolfgang Bangerth

1
@ WolfgangBangerth : C ++ 11로 전환하는 것에 대한 일반적인 의견이었습니다. 어느 쪽이든 C ++ 11은 std :: complex의 대부분의 문제점을 수정하지 않습니다.
Jack Poulson

7

나는 std::complex<>내 프로그램에서 사용 하며 각각의 새로운 컴파일러 또는 컴파일러 업그레이드에 대한 컴파일러 플래그 및 해결 방법과 싸워야합니다. 나는이 싸움들을 시간 순서대로 설명하려고 노력할 것이다.

  1. std::norm|z|2|z|-ffast-math
  2. Linux (또는 링커)의 인텔 icc 컴파일러는 std::arg특정 구성 (비교적 gcc- 버전과의 링크 호환성)에서 비 선택으로 컴파일 되었습니다. 문제가 너무 자주 재 포장되었으므로 std::arg로 대체해야했습니다 atan2(imag(),real()). 그러나 새로운 코드를 작성할 때 이것을 잊어 버리는 것은 너무 쉽다.
  3. 이 유형 std::complex은 내장 C99 복합 유형과 다른 통화 규칙 (= ABI) 및 최신 gcc 버전에 대한 내장 포트란 복합 유형을 사용합니다.
  4. -ffast-math예상치 못한 방법으로 소수점 예외 부동의 처리와 컴파일 플래그 상호 작용. 컴파일러가 디비전을 루프 밖으로 끌어내어 division by zero런타임에 예외 가 발생합니다. 이러한 예외는 주변 논리로 인해 해당 분할이 발생하지 않았기 때문에 루프 내에서 발생하지 않았을 것입니다. 부동 소수점 예외 처리 (다른 컴파일 플래그 사용)를 사용하고 이러한 문제가 발생하는 프로그램과 별도로 컴파일 된 라이브러리이기 때문에 실제로는 나빴습니다. 이 문제는 실제로 나쁜 문제를 일으켰습니다). 이것은 컴파일러가 직접 사용하는 최적화를보다주의 깊게 수행함으로써 해결되었습니다.
  5. 라이브러리는 프로그램의 일부가되어 더 이상 -ffast-math컴파일 플래그를 사용하지 않았습니다 . 최신 gcc 버전으로 업그레이드 한 후 성능이 크게 떨어졌습니다. 이 문제를 아직 자세히 조사하지는 않았지만 C99 Annex G 와 관련이 있다고 생각합니다 . 나는 복잡한 숫자에 대한이 곱셈의 이상한 정의에 완전히 혼란스러워하고 다른 버전이 잘못 인도되었다는 주장과 함께 다른 버전이 존재하는 것으로 보입니다. 이 새로운 gcc 버전 -fcx-limited-range과 관련된 다른 문제가있는 것처럼 보이기 때문에 컴파일 플래그가 문제를 해결할 수 있기를 바랍니다 -ffast-math.
  6. -ffast-math컴파일 플래그의 동작한다 NaNGCC의 새 버전을 완전히 예측할 수없는 (심지어 isnan영향을). 유일한 해결 방법은 NaN프로그램의 존재 를 피하는 것 입니다 NaN.

이제 내장 복잡한 유형을 포기할 것인지 여부와 std::complex이러한 이유로 물어볼 수 있습니다 . C ++을 사용하는 한 내장 유형을 유지합니다. C ++이 과학 컴퓨팅에 완전히 사용할 수 없게되어야하는 경우 과학 컴퓨팅과 관련된 문제를보다 잘 처리하는 언어로 전환하려고합니다.


C99 Annex G와 관련된 나의 두려움이 실현 된 것처럼 보이며 복잡한 숫자를 곱할 때 적절한 계산 속도에 -fcx-limited-range가 필요합니다. 적어도 그게 내가 다음과 같은 최근의 전쟁 이야기에서 무엇을 얻을 수 있습니다 : medium.com/@smcallis_71148/...는
토마스 Klimpel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.