я использую 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. Массивы комплексных чисел также адресуются.