В программе несколько однотипных функций, вычисляющих интеграл методом Симпсона.
double idens(double x,double y) {
int steps,c;
double rn, sumn, sprev, steplength, extra;
extra=2*dens(x,y,0.5);
sumn=dens(x,y,0)+dens(x,y,1)+2*extra;
steps=1;
do {
steps*=2; sprev=sumn; steplength=(1.0/steps/2); sumn-=extra; extra=0;
for (c=0; c<steps; c++){
extra+=dens(x,y,c*2+1)*steplength)*2; }
sumn+=extra*2;
rn=(sumn/6.0/steps-sprev/3.0/steps);
if (rn<0) {rn=-rn;};
} while (rn>epsilon);
return sumn;}
Различаются они только вызываемой подинтегральной функцией вида double dens(double x, double y, double z)
Вопрос: имеет ли смысл обозначить dens как переменную и заменить все интегрирующие функции на одну? Или это замедлит программу?
Заранее спасибо.
[offtop]Было бы неплохо сразу, при запуске, составить таблицу решений, а потом брать значения из неё, а не вычислять каждый раз новое значение в цикле.[/offtop]
> Имеет. Я вообще не очень понимаю, зачем тебе несколько разных функций, которые реализуют один и тот же метод.
А вы например вкурсе почему плюснутый std::sort быстрее пуре-си qsort-а? :)
По теме: вызов функции через указатель -- дорогая неоптимизируемая операция, если нужна максимальная прозиводительность, и при этом generic programming-а хочется, пишите либо макросами либо на плюсы с темплейтами переходите (что разумнее будет).
> Было бы неплохо сразу, при запуске, составить таблицу решений, а потом брать значения из неё, а не вычислять каждый раз новое значение в цикле.
В смысле? Для каждой комбинации x,y,z dens(x,y,z) вычисляется всего один раз, если я ничего не напутал. Всего точек x,y -- от 250 000 до 5 000 000. Заранее всё вычислить?
>> вызов функции через указатель -- дорогая неоптимизируемая операция,
> Насколько дорогая?
Лучше тебе проверить это. Вообще-то на современных процессорах вызов по указателю уже не является дорогой операцией, но, конечно, он дороже inline-варианта.
> Насколько дорогая?
AFAIK остановка/сброс конвейра част происходят, на таких вызовах, а это жутко дорого.
> Которые препроцессор потом развернёт в несколько однотипных функций, как сейчас?
Так це же компилятор, для достижения максимальной производительности,
мелкие функции всегда инлайнятся.
> Можно ссылку на пример?
template<double FN(double)>
double doSOmething(double x, double y)
{
return x*y + FN(x*y);
}
res = doSomething<RealFunc>(1,2);
Andrew Robb, using a different system, was unable to reproduce the results; on his system, qsort was faster than std::sort. He also has a merge sort routine that only works with arrays (not STL vector and deque), but sorts faster than std::sort. This also shows that if you work hard, you can get something faster than STL.
> Аргументы закончились и начались обычные наезды ?
Блин, баклан, ну сравни сам std::sort хоть тупо, для обычного int массива, и qsort.
#include <stdlib.h>
#include <time.h>
#include <algorithm>
enum { NR = 10000000 };
int arrA[NR];
int arrB[NR];
int cmpC(const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
int main()
{
for (int i=0; i<NR; i++)
{
arrA[i] = arrB[i] = rand();
}
time_t t1 = time(NULL);
qsort(arrA, NR, sizeof(int), cmpC);
time_t t2 = time(NULL);
std::sort(&arrB[0], &arrB[NR]);
time_t t3 = time(NULL);
printf("pure C qsort:\t%d\nC++ std::sort:\t%d\n", t2-t1, t3-t2);
}
$ g++ -Os 1.cpp -o 1 && ./1
pure C qsort: 4
C++ std::sort: 1
$ g++ --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5483)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ uname -a
Darwin mac46.local 9.2.0 Darwin Kernel Version 9.2.0: Tue Feb 5 16:13:22 PST 2008; root:xnu-1228.3.13~1/RELEASE_I386 i386
Все кто советует заранее вычислять таблицу решений плохо понимают что если нужна высокая точность а следовательно и большая таблица то этот вариант КРАЙНЕ неадекватен потому что одно значение в таблице 4 или 8 байтов, а далее помножаем на размер таблицы и ... сколько у вас эти таблички места займут? Сейчас у вас 5миллионов а завтра нужно будет 500 миллионов и? По опыту скажу так - если вы уверены что вам НЕ прижмет повышать точность (делать больше разбиений) то делайте таблички если нет то лучше не надо ибо как только данные для счетной программы вываливаются из ОЗУ в своп все считайте времени выполнения полный пи..ц оно растет как минимум в 10(для BSD) а то и в 100(Для window) раз, и тут дешевше лишний раз посчитать функцию...
результаты с linux машины, с 1-в-1 таким-же Core 2 Duo что и у мака:
pure C qsort: 46
C++ std::sort: 17
$ g++ --version
g++ (GCC) 4.1.2 20061115 (prerelease) (SUSE Linux)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$uname -a
Linux testhost 2.6.18.2-34-default #1 SMP Mon Nov 27 11:46:27 UTC 2006 i686 i686 i386 GNU/Linux
Там зузя 10.2 старая. Что не так, почему сортировка в 10 раз медленее чем на маке работает ? Неужто особенности VM Linux-ового, по сравнению с Mach-овским, такую разницу дают?
>Что не так, почему сортировка в 10 раз медленее чем на маке работает ? Неужто особенности VM Linux-ового, по сравнению с Mach-овским, такую разницу дают?
Если ты из моего поста взял - там нолик добавлен NR = 100000000.
Преждевременная оптимизация - корень всех бед. Реализуй самым простым и понятным способом, потом, если скорости будет не хватать, бери профайлер и им ищи и устраняй узкие места.
5 000 000 точек, с инлайновой подинтегральной функцией 15 секунд, с вызовом по указателю 17. Жить можно. Процессор -- Athlon 64 в 32-битном режиме. На Celeronах будет сильно отличаться?