У меня есть довольно сложная функция, которая принимает несколько двойных значений, которые представляют два вектора в 3-х пространствах формы (величина, широта, долгота), где широта и долгота указаны в радианах, и угол.Цель функции - повернуть первый вектор вокруг второго на заданный угол и вернуть результирующий вектор.Я уже проверил, что код логически корректен и работает.
Ожидаемое назначение функции для графики, поэтому двойная точность не требуется;однако на целевой платформе функции trig (и sqrt), которые принимают числа с плавающей запятой (в частности, sinf, cosf, atan2f, asinf, acosf и sqrtf), работают быстрее с двойными числами, чем с числами с плавающей запятой (вероятно, потому что инструкция для вычисления таких значений может фактически потребоватьdouble; если передано значение с плавающей запятой, значение должно быть приведено к двойному значению, что требует копирования его в область с большим объемом памяти - т. е. накладные расходы).В результате все переменные, включенные в функцию, имеют двойную точность.
Вот проблема: я пытаюсь оптимизировать свою функцию так, чтобы ее можно было вызывать больше раз в секунду.Поэтому я заменил вызовы sin, cos, sqrt и так далее вызовами версий этих функций с плавающей запятой, поскольку они приводят к общему увеличению скорости в 3-4 раза.Это работает почти для всех входов;однако, если входные векторы близки к параллельным со стандартными единичными векторами (i, j или k), ошибок округления для различных функций накапливается достаточно, чтобы вызвать последующие вызовы функций sqrtf или обратного триггера (asinf, acosf,atan2f) передать аргументы, которые едва находятся вне области действия этих функций.
Итак, я остаюсь с этой дилеммой: либо я могу вызывать только функции двойной точности и избежать проблемы(и в конечном итоге с ограничением около 1 300 000 векторных операций в секунду), или я могу попытаться придумать что-то еще.В конечном счете, я хотел бы найти способ санировать входные данные для функций обратного триггера, чтобы позаботиться о крайних случаях (это тривиально для sqrt: просто используйте abs).Ветвление не вариант, так как даже один условный оператор добавляет столько накладных расходов, что любой прирост производительности теряется.
Итак, есть какие-нибудь идеи?
Редактировать: кто-то выразил недоумение по поводу того, что я использую удвоение по сравнению соперации с плавающей запятой.Функция намного быстрее, если я на самом деле храню все свои значения в контейнерах двойного размера (переменные двойного типа IE), чем если бы я сохранял их в контейнерах плавающего размера.Однако триггерные операции с плавающей запятой выполняются быстрее, чем триггерные операции с двойной точностью по очевидным причинам.