Почему флаг оптимизации (-O3) не ускоряет вычисления в четыре раза?

У меня есть высокоточный ODE (обыкновенные дифференциальные уравнения) решатель, написанный на C++. Я делаю все вычисления с пользовательским типом real_type, Существует typedef, объявляющий этот тип в заголовке:

typedef long double real_type;

Я решил изменить длинный двойной тип на __float128 для большей точности. В дополнение к этому я включил quadmath.h и заменил все стандартные математические функции на те из libquadmath.

Если "длинная двойная" версия создается без каких-либо флагов оптимизации, некоторый эталонный ODE решается за 77 секунд. Если эта версия построена с флагом -O3, то же ODE решается за 25 секунд. Таким образом, флаг -O3 ускоряет вычисления в три раза.

Но в версии "__float 128", собранной без флагов, аналогичный ODE решается за 190 секунд, а с -O3 - за 160 секунд (разница ~ 15%). Почему оптимизация -O3 дает такой слабый эффект для вычислений с четверной точностью? Может быть, я должен использовать другие флаги компилятора или включить другие библиотеки?

3 ответа

Решение

Оптимизация компилятора работает следующим образом: компилятор распознает определенные шаблоны в вашем коде и заменяет их эквивалентными, но более быстрыми версиями. Не зная точно, как выглядит ваш код и какие оптимизации выполняет компилятор, мы не можем сказать, чего не хватает компилятору.

Вполне вероятно, что несколько оптимизаций, которые компилятор знает, как выполнить для собственных типов с плавающей запятой и их операций, он не знает, чтобы выполнить на __float128 и реализации библиотек операций. Он может не распознавать эти операции такими, какие они есть. Может быть, он не может смотреть на реализации библиотеки (вы должны попробовать скомпилировать библиотеку вместе с вашей программой и включить оптимизацию во время соединения).

Та же оптимизация обеспечила практически одинаковую выгоду. Процент снизился только потому, что сама математика заняла больше времени.

Чтобы полагать, что оптимизации должны составлять тот же процент, вы должны полагать, что если математика займет больше времени, оптимизатор найдет больше сбережений. Почему ты так думаешь?

Если ваша цель - архитектура x86, то в GCC __float128 является фактическим типом FP ​​четверной точности, в то время как long double это 96-битный тип FP x87 (расширенный дважды).

Разумно, что математика с типами меньшей точности может быть быстрее, чем математика с типами большей точности. Также разумно, что математика с нативными типами оборудования может быть быстрее, чем математика с неродными типами.

Другие вопросы по тегам