Чому комп'ютерному вченому потрібно реалізувати власну версію std :: complex?


14

Багато відомих бібліотек C ++ в обчислювальній науці, такі як Eigen , Trilinos і deal.II використовують стандартний об'єкт бібліотеки заголовків шаблонів C ++ std::complex<>, щоб представити складні числа з плаваючою комою.

У Джека Poulson в відповідь на питання про конструктори по замовчуванням, він вказує на те , що у нього є своя власна здійснення std::complexв Elemental «по ряду причин». Які ці причини? Які переваги та недоліки у цього підходу?

Відповіді:


16

Я вважаю, що ця дискусія неодноразово виникала у списку PETSc. Мої основні причини:

  1. Стандарт C ++ зазначає, що std :: complex визначається лише для типів даних float, double та long double. Таким чином, його не можна використовувати для інших типів даних, таких як квадратологія.

  2. Стандарт не дає гарантій щодо стабільності складної арифметики.

  3. Стандарт не дає гарантії, що дані в комплексі std :: зберігаються як реальний компонент, за яким слід уявний компонент. Це має вирішальне значення для інтерфейсів із зовнішніми бібліотеками, такими як BLAS та LAPACK. Це стосується всіх основних реалізацій, але я б вважав за краще це забезпечити.

  4. Я вважаю за краще мати можливість безпосередньо маніпулювати реальними та уявними компонентами. std :: complex робить це непотрібно складним.

  5. Я хотів би врешті-решт мати більш загальну версію, яка вимагає, щоб тип даних був кільцем, а не вимагав поля. Сюди входили б цілі числа Гаусса.


6
Точка 3 розглянута в C ++ 11. 26.4.4 зазначається, що якщо zвираз значення lv значення типу cv, std::complex<T> то reinterpret_cast<cv T(&)[2]>(z)і reinterpret_cast<cv T(&)[2]>(z)[0]позначає реальну частину z, і reinterpret_cast<cv T(&)[2]>(z)[1]позначає уявну частину z. Адресуються також масиви складних чисел.
Джеймс Кастер

3
@JamesCuster: Я все для того, щоб врешті-решт перейти на C ++ 11, але наукові коди, які хочуть залишатися переносними для напівекзотичних архітектур, мабуть, повинні почекати ще щонайменше два-три роки, щоб зробити це. На жаль, C ++ 11 вирішує лише частину проблеми.
Джек Поульсон

Я розумію, я просто викидав його на випадок, якщо хтось дивиться на це питання в майбутньому.
Джеймс Кастер

2
Ну, я думаю, що це копієць, щоб сказати, що вам доведеться почекати, поки компілятори підтримують C ++ 11. Явна вимога була введена в новий стандарт, оскільки всі існуючі реалізації вже підтримують його. Я не можу придумати випадок, коли було б небезпечно вже припускати саме цей макет у існуючих компіляторах / бібліотеках, оскільки просто не було б сенсу реалізувати std :: complex будь-яким іншим способом.
Вольфганг Бангерт

1
@WolfgangBangerth: Це був більше загальний коментар щодо переходу на C ++ 11. Так чи інакше, C ++ 11 не виправляє більшості проблем зі std :: complex.
Джек Поульсон

7

Я використовую std::complex<>у своїх програмах, і мені доводиться боротись із прапорами компілятора та способом вирішення кожного нового компілятора чи оновлення компілятора. Я спробую перерахувати ці поєдинки в хронологічному порядку:

  1. Вимірювання продуктивності показали, що крок, що включає лише обчислення площі абсолютного значення поля складних чисел, за gcc-4.x зайняв більше часу, ніж попередній FFT. Копання в сформованому коді асемблера показало, що std::norm( ) обчислювало абсолютне значення ( ) таким чином, щоб уникнути переповнення, а потім підкреслити результат. Цю проблему можна вирішити прапором компіляції .| z ||z|2|z|-ffast-math
  2. Компілятор Intel icc на linux (або linker) компілюється std::argдля не-вибору в певних конфігураціях (сумісність посилань із певною версією gcc). Проблема виникала занадто часто, тому її std::argдовелося замінити на atan2(imag(),real()). Але було занадто просто забути це, коли писав новий код.
  3. Тип std::complexвикористовує різні умови викликів (= ABI), ніж комплексний тип вбудованого C99, а вбудований комплексний тип Fortran для новіших версій gcc.
  4. У -ffast-mathкомпіляції прапор взаємодіє з обробкою з плаваючою точкою виключення несподіваним чином. Що відбувається - компілятор витягує поділи з циклів, тим самим спричиняючи division by zeroвинятки під час виконання. Ці винятки ніколи б не траплялися всередині циклу, оскільки відповідний поділ не відбувся через навколишню логіку. Це було дуже погано, оскільки це була бібліотека, яка була складена окремо від програми, яка використовувала передачу виключень із плаваючою комою (використовуючи різні прапорці компіляції) та натрапила на ці випуски (відповідні команди сиділи в різних частинах світу, так це питання справді спричинило погані неприємності). Це було вирішено, зробивши оптимізацію, яку використовував компілятор вручну, більш ретельно.
  5. Бібліотека стала частиною програми і більше не використовувала -ffast-mathпрапор компіляції. Після оновлення до новішої версії gcc продуктивність знизилася на величезний фактор. Я ще не детально досліджував це питання, але побоююсь, що він пов'язаний із додатком C99 C99 . Я мушу визнати, що мене цілком бентежить це дивне визначення множення на складні числа, і навіть, здається, існують різні версії цього з твердженнями, що інші версії помилково керуються. Я сподіваюся, що -fcx-limited-rangeпрапор компіляції вирішить проблему, тому що, здається, є ще одна проблема, пов’язана з -ffast-mathцією новою версією gcc.
  6. -ffast-mathПрапор компіляції робить поведінку NaNабсолютно непередбачуваним для нових версій GCC (навіть isnanвражений). Здається, єдиним способом вирішення проблеми є уникнення будь-якої появи NaNв програмі, яка перемагає мету існування NaN.

Тепер ви можете запитати, чи я планую відмовитися від вбудованих складних типів і std::complexз цих причин. Я залишатимусь із вбудованими типами, поки я залишаюся з C ++. У випадку, якщо C ++ вдасться стати абсолютно непридатним для наукових обчислень, я б вважав за краще перейти на мову, яка б більше піклувалася про питання, що стосуються наукових обчислень.


Схоже, мої побоювання, пов'язані з додатком C99 С, справдилися, і -fcx з обмеженим діапазоном тепер начебто потрібна для гідної швидкості обчислення при множенні складних чисел. Принаймні, це те, що я отримую з наступної недавньої історії війни: medium.com/@smcallis_71148/…
Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.