я использую std::complex<>
в своих программах, и мне приходится бороться с флагами компилятора и обходным путем для каждого нового обновления компилятора или компилятора. Я постараюсь перечислить эти бои в хронологическом порядке:
- Измерения производительности показали, что этап, включающий только вычисление квадрата абсолютного значения поля комплексных чисел, занимает больше времени, чем предыдущий FFT для gcc-4.x. Копание в сгенерированном ассемблерном коде показало, что
std::norm
(| Z|2) вычислили абсолютное значение (| Z|) таким образом, чтобы избежать переполнения, а затем возвести в квадрат результат. Эта проблема может быть исправлена с помощью флага компиляции -ffast-math
.
- Компилятор intel icc на linux (или компоновщике) скомпилирован
std::arg
для non-opt при определенных конфигурациях (совместимость ссылок с определенной версией gcc). Проблема всплывала слишком часто, поэтому std::arg
пришлось заменить на atan2(imag(),real())
. Но было слишком легко забыть об этом при написании нового кода.
- Тип
std::complex
использует другие соглашения о вызовах (= ABI), чем встроенный комплексный тип C99, и встроенный комплексный тип Fortran для более новых версий gcc.
- В
-ffast-math
компиляции флаг взаимодействует с обработкой с плавающей точкой исключения неожиданным образом. Что происходит, так это то, что компилятор вытягивает деления из циклов, вызывая тем самымdivision by zero
исключения во время выполнения. Эти исключения никогда бы не произошли внутри цикла, потому что соответствующее деление не произошло из-за окружающей логики. Это было действительно плохо, потому что это была библиотека, которая была скомпилирована отдельно от программы, которая использовала обработку исключений с плавающей запятой (используя разные флаги компиляции) и сталкивалась с этими проблемами (соответствующие команды сидели в разных частях света, поэтому эта проблема действительно вызвала неприятности). Это было решено путем более тщательной оптимизации, используемой компилятором вручную.
- Библиотека стала частью программы и больше не использовала
-ffast-math
флаг компиляции. После обновления до более новой версии gcc производительность сильно упала. Я еще детально не исследовал эту проблему, но боюсь, что она связана с Приложением G C99 . Я должен признать, что я совершенно смущен этим странным определением умножения для комплексных чисел, и даже кажется, что существуют разные версии этого с утверждениями, что другие версии ошибочны. Я надеюсь, что -fcx-limited-range
флаг компиляции решит проблему, потому что, похоже, есть еще одна проблема, связанная с -ffast-math
этой более новой версией gcc.
-ffast-math
Флаг компиляции делает поведение NaN
совершенно непредсказуемым для новых версий GCC (даже isnan
пораженный). Единственный обходной путь, по-видимому, состоит в том, чтобы избежать любого вхождения NaN
в программе, что противоречит цели существования NaN
.
Теперь вы можете спросить, планирую ли я отказаться от встроенных сложных типов и std::complex
по этим причинам. Я останусь со встроенными типами, пока я остаюсь с C ++. В случае, если C ++ станет полностью непригодным для научных вычислений, я бы предпочел перейти на язык, который больше заботится о проблемах, связанных с научными вычислениями.
z
является выражением lvalue типа 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
. Массивы комплексных чисел также адресуются.