Здравствуйте.
Есть кусок кода, который активно использует функцию frexp():
double frexp(
double x,
int *expptr
);
Gets the mantissa and exponent of a floating-point number.
Компилятор -- MS VC++ 9.0, релиз, оптимизация по скорости.
Профайлер показывает, что эта функция занимает 30% процессорного времени. Если смотреть в asm, то видно, что frexp() вызывается через call, причём внутри она вызывает ещё несколько вспомогательных функций. Intrinsic'a для frexp() в MSVC похоже нет, и заставить компилятор генерировать код без инструкций call я не смог.
Вопрос: как достать из double'а экспоненту и мантиссу максимально быстро?
Я не знаком глубоко с системой команд x86/87, но подозреваю, что FPU должен уметь это делать (знатоки, что скажете?). Очень хочется избваится от call'ов.
Лучшее что я пока придумал -- это доставать мантиссу/экспоненту зная побитное представление double'а при помощи битовых операций. Работает заметно быстрее чем frexp(), но выглядит не элегантно.
А как ещё?
Здравствуйте, cepstr, Вы писали:
C>Вопрос: как достать из double'а экспоненту и мантиссу максимально быстро?
C>Я не знаком глубоко с системой команд x86/87, но подозреваю, что FPU должен уметь это делать (знатоки, что скажете?). Очень хочется избваится от call'ов.
Команда называется fxtract, но насчет быстрее/медленнее надо проыодить эксперименты.
--
Sergey Chadov
... << RSDN@Home 1.2.0 alpha rev. 685>>
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, cepstr,
P>http://www.rsdn.ru/article/alg/float.xmlАвтор(ы): Сергей Холодилов
Дата: 15.03.2008
Если яблоко поровну разделить на троих, каждому достанется треть. Так в нашу жизнь входят дроби, примерно с теми же целями входят они и в программирование.. Но реализация дробей в виде типов данных float/double ведёт себя не совсем "математично". В чём причина отличий, как минимизировать их влияние на результат вычислений, как же всё это всё-таки реализовано и почему запятая плавает — читайте в статье.
здесь описание формата
union parsed_double
{
double v; // значение
struct
{
unsigned int m0; // младшие биты мантиссы
unsigned int m1 : 20; // старшие биты мантиссы
unsigned int e : 11; // показатель степени
unsigned int s : 1; // знак
} d;
};
inline double __frexp(double value, int* exponent)
{
parsed_double& pd = (parsed_double&)value;
*exponent = pd.d.e - 1022;
pd.d.e = 1022;
return value;
}
test_count: 1000000, frexp(12345.12345)
frexp:1969 ms
__frexp:219 ms
Здравствуйте, sokel, Вы писали:
S>Здравствуйте, Programador, Вы писали:
P>>Здравствуйте, cepstr,
P>>http://www.rsdn.ru/article/alg/float.xmlАвтор(ы): Сергей Холодилов
Дата: 15.03.2008
Если яблоко поровну разделить на троих, каждому достанется треть. Так в нашу жизнь входят дроби, примерно с теми же целями входят они и в программирование.. Но реализация дробей в виде типов данных float/double ведёт себя не совсем "математично". В чём причина отличий, как минимизировать их влияние на результат вычислений, как же всё это всё-таки реализовано и почему запятая плавает — читайте в статье.
здесь описание формата
или даже так побыстрей будет, только надо проверки на граничные значения ещё прицепить:
inline double __frexp(double value, int* exponent)
{
__int64& ivalue = (__int64&) value;
*exponent = (int)((ivalue&0x7FF0000000000000L)>>52) - 1022;
ivalue&=0x800FFFFFFFFFFFFFL;
ivalue|=0x3FE0000000000000L;
return value;
}