Действительно ли возможно прокрутить значительно более быструю версию modf

В приложении я являюсь профильным, я нашел, что в некоторых сценариях эта функция может принять 10% общего времени выполнения.

MSVC ++ компилятор 2008 года используется для ссылки... Я не вспоминаю, отображается ли modf на единственную инструкцию или если там вероятно любой способ сделать его быстрее.

см. также здесь для подобного вопроса на функции sqrt

В отличие от sqrt, я действительно не знаю, как modf работает. Существует ли операция по сборке? Например, Вы могли сделать:

modf(float input,int &intPart, float &floatPart)
{
 intPart= (int)input;
 floatPart= input - intPart;
}

Но я предполагаю, что это подвергается штрафам от кастинга/преобразования, и т.д. как внедрение FAST работает?

5
задан Community 23 May 2017 в 12:18
поделиться

6 ответов

Здесь вы получаете хорошие ответы, но где же остальные 90% времени уходят?

Не смотрите на исключительный% времени на процедуру .

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

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

Простой способ получить эту информацию - этот метод .

Добавлено: по мере того, как вы найдете оптимизацию, которую вы можете сделать, ожидайте, что общее время выполнения уменьшится, но не ожидайте, что процентное соотношение обязательно снизится. Ваш% времени в modf и / или sqrt может фактически увеличиться, если вы избавитесь от других вещей, или они могут упасть, если вы обнаружите, что вы можете их запомнить (и, следовательно, вызвать их меньше), например.

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

2
ответ дан 14 December 2019 в 19:07
поделиться

Ваша реализация, вероятно, самая быстрая из возможных на x86. Однако имейте в виду, что вы ограничили поддерживаемый диапазон ввода диапазоном int !

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

0
ответ дан 14 December 2019 в 19:07
поделиться

Хорошая реализация modf может быть довольно быстрой (порядка 10 циклов на текущем оборудовании). Плохая реализация может быть довольно медленной (порядка 100 циклов). Действительно плохо продуманная реализация может занять 1000 циклов. Я не знаю, в каком состоянии находится реализация Microsoft, но есть несколько хороших реализаций в различных библиотеках C с открытым исходным кодом, на которые вы можете взглянуть.

Предложенная вами реализация использует некоторые сокращения и не соответствует стандарту Си; в частности, она будет вести себя довольно плохо в случае, когда input слишком велик для успешного преобразования в целое число. Кроме того, в некоторых случаях он неправильно определяет знак нуля, но вас это может не волновать.

Заметим также, что вам будет полезно использовать компилятор / библиотеку C, поддерживающую стандарт C99, поскольку тогда вы сможете воспользоваться функцией modff и избежать накладных расходов на преобразование в двойную точность и обратно. Я знаю, что математическая библиотека Intel (которая поставляется с их компиляторами) имеет отличные реализации modf и modff. GCC также поддерживает варианты C99 с одинарной точностью.

FWIW, я проверил предложенную вами реализацию, и (при условии отличного кодегена компилятора) она примерно на 50% быстрее, чем библиотека Intel modff (реализация Intel, однако, выдает правильный результат для всех входов). Самая быстрая корректная реализация, которую я тестировал, всего на 15% медленнее вашей (но, опять же, выдает правильный результат для всех входов и даже правильно устанавливает флаги состояния с плавающей точкой).

2
ответ дан 14 December 2019 в 19:07
поделиться

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

Когда функция инлайнится, если вы всегда используете только одну из мантисс/экспонент, компилятор должен быть достаточно умным, чтобы выдавать код для вычисления только этой части, что еще больше ускорит работу.

Если вы все еще заинтересованы в создании собственного, посмотрите в википедии о формате с плавающей точкой

1
ответ дан 14 December 2019 в 19:07
поделиться

Я также встречал случаи, когда небольшие подпрограммы при вызове из библиотеки DLL (как в случае с CRT) сильно пострадали от связующего кода при получении в и из DLL. В таком случае, сворачивание собственного и изменение способа его компиляции (например, его встраивание) может дать вам повышение производительности, даже если сама реализация идентична. YMMV, POITROAE и т. Д.

0
ответ дан 14 December 2019 в 19:07
поделиться

Обратите внимание, что библиотека должна предлагать максимально быстрое решение, которое работает во всех угловых случаях, что, например, добавляет немало сложности.

Если ваша версия с приведением типов работает нормально для вашей программы, это означает, что у вас нет чисел с плавающей запятой, выходящих за пределы диапазона int, и либо вы подтвердили, что она работает правильно для отрицательных чисел, либо вы не заботьтесь о них, тогда это, вероятно, будет немного быстрее.

0
ответ дан 14 December 2019 в 19:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: