Мой первый пост здесь.Отличный сайт и ресурс.
Я немного поискал и посмотрел на вопросы с похожими названиями, но не смог найти что-то конкретное по этому поводу.
Я пытаюсь удалить любую избыточностьи раздувать из библиотеки C астрономических расчетов, которую использует моя программа на C ++.Я запустил простой профилировщик (VerySleepy).
Вот код, который профилировщик показывал как наиболее часто используемый (кроме функций библиотеки C sprintf и т. Д.):
double swi_echeb(const double x, const double* const coef, const int ncf)
{
int j = ncf - 1;
double x2, br, brp2, brpp;
x2 = x * 2.;
br = 0.;
brp2 = 0.; /* dummy assign to silence gcc warning */
brpp = 0.;
for (; j >= 0; --j) { // <-- 0.39s
brp2 = brpp; // <-- 0.01s
brpp = br; // <-- 0.32s
br = x2 * brpp - brp2 + coef[j]; // <-- 3.49s ***
} // <-- 0.14s
return (br - brp2) * .5; // <-- 0.06s
} // <-- 0.05s
Thisопределенная функция глубоко встроена в другие, и основная функция «запуска», которую вызывает моя программа, вызывается тысячи раз.
Вы можете увидеть выдающийся оператор с на 3,49 с намного выше, чем все остальные операторы.,Я знаю, что есть способы ускорить арифметику C с использованием умножения над делением, когда это возможно.Но я не знаю намного больше.
Как:
Было бы лучше разделить это утверждение на более мелкие части?:
br = x2 * brpp;
br -= brp2;
br += coef[j];
Любые другие идеи или критические замечания.Я не писал этот код, хотя я добавил const к параметрам функции, так как мне нравится const -корректность.
Я никогда раньше не пытался использовать регистры или другие хитрые трюки, чтобы ускорить процесс.Кто-нибудь думает, что что-то подобное может работать здесь?
Я знаю, что люди скажут: "Попробуйте!"Поэтому я сделаю и обновлю то, что я получу, если это поможет кому-либо с похожими арифметическими вопросами.
РЕДАКТИРОВАТЬ: публикация результатов, которые я протестировал из предложений
Для того, чтобысамый быстрый, самый медленный, вот что я нашел до сих пор.Профилировщик очень спящий.Компилятором является Visual Studio 2008 Pro Ed.Варианты компиляции для библиотеки и моего приложения:
Debug, C7 format, /O2 /Ob2 /Oi /Ot /Oy /GT /GL /GF /FD /MTd /GS- /Gy /fp:fast /FAs
Ниже приводится предложение Эндрю о выполнении "4 итераций в цикле".До сих пор это был самый быстрый результат.
ОБЩЕЕ ВРЕМЯ, потраченное на функцию (здесь время от других операторов в функции не показано) = 2,08 секунды
for (; index >= 3; index -= 4) { // 0.02s
brp2 = brpp;
brpp = br; // 0.02s
br = x2 * brpp - brp2 + coef[index]; // 0.25s
brp2 = brpp;
brpp = br; // 0.13s
br = x2 * brpp - brp2 + coef[index - 1]; // 0.33s
brp2 = brpp;
brpp = br; // 0.13s
br = x2 * brpp - brp2 + coef[index - 2]; // 0.34s
brp2 = brpp;
brpp = br; // 0.14s
br = x2 * brpp - brp2 + coef[index - 3]; // 0.42s
}
for (; index >= 0; --index) { // 0.03s
brp2 = brpp; // 0.03s
brpp = br;
br = x2 * brpp - brp2 + coef[index]; // 0.11s
}
Следующим быстрым был исходный неизмененный код с общим временем 2,39 секунды внутри функции, снова включив операторы вне цикла.Обратите внимание, что это меньше, чем мой оригинальный пост.Мой оригинальный пост был неоптимизированным кодом, но поскольку все предлагали его, все мои тесты были впоследствии настолько оптимизированы, насколько я мог получить в VS08:
for (j = ncf - 1; j >= 0; j--) { // 0.02s
brp2 = brpp; // 0.03s
brpp = br; // 0.07s
br = x2 * brpp - brp2 + coef[j]; // 2.14s
}
После этого оригинального кода следующим быстрым было представление Дрю о настройке.указатель заранее и используя это. Общее время, потраченное внутри функции, составило 2,49 секунды , включая время из операторов вне цикла:
for (; index >= coef; --index) { // 0.01s
brp2 = brpp;
brpp = br; // 0.06s
br = x2 * brpp - brp2 + *index; // 2.24s
}
Я также попробовал сочетание развертывания цикла Эндрю и использования указателя Дрю, но это заняло 2,39 секунды , то же самое, что и неизмененный код.
Исходя из результатов, развертывание цикла - это путь для моего использования.