Linux.org.ua
Технічні питання => Розробка => Гілку створено: Паша від 2005-12-14 22:46:44
-
У програмі є цикл, що крутиться приблизно мільйон разів. Логічно зробити так, щоб одна ітерація займала найменеше часу. Який оператор швидкіший :D ? for чи while? Чи може вони однаково компілюються? Що порадите?
-
оптимізація компілятора в більшості випадків позбовляє сенсу таку "оптимізацію".
ще запитай що швидше ++i vs i++ :)))
-
Я про це здогадувавсь. Але ж все таки мільйон ітерацій...
-
Теоретично for буде трохи швидшим, оскільки має чітко визначену кількість повторень і не потребує перевірки умови виходу. В асемблерному коді це буде просто повторення деякої ділянки коду n разів... А у випадку з while буде ще перевірка умови (типу кількість повторень < 1000000). Але я не думаю, що різниця в швидкодії навіть буде помітною... А взагалі, якщо у вас в середині циклу якісь математичні вирази, то краще їх спочатку спростити за допомогою /dev/hands, порахувати окремо все, що можна порахувати за межами циклу, уникати рекурсій і т.п.
-
головне, дядьку, не капелюх, а те, що під ним :) (тобто в середині циклу), але якщо вже є таке нестерпне бажання знати, є два шляхи:
1) скомпілювати обидва варіанти з gcc -S і подивитись асемблерний код
2) скомпілювати обидва варіанти і зробити time myprog (бажано декілька разів)
-
Теоретично for буде трохи швидшим, оскільки має чітко визначену кількість повторень і не потребує перевірки умови виходу. В асемблерному коді це буде просто повторення деякої ділянки коду n разів... А у випадку з while буде ще перевірка умови (типу кількість повторень < 1000000). Але я не думаю, що різниця в швидкодії навіть буде помітною
дивна теорія. :) чому ти вирішив що для цикла фор якись блок буде повторюватися N раз? і чому вважаєш що кількість ітерацій всередені відома на єтапі компіляції?
ось тобі найпростіший варіант
std::vector<InterDat>::const_iterator it, end;
it = sections_.begin();
end = sections_.end();
for(; it != end; ++it)
{
..........
розмір вектора може динамічно змінюватися так що вставити N блоків компілятору навряд чи вдасться і перевірка умови також є
-
Взагалі-то будь-який цикл в сях можна виразити через for, так що все це syntactic sugar чистої води.
Питання має стояти, як взагалі має виглядати тіло циклу.
-
std::vector<InterDat>::const_iterator it, end;
it = sections_.begin();
end = sections_.end();
for(; it != end; ++it)
{
..........
Ой, чур мене, STL:) Вибачаюсь, був не правий, мислення у мене паскалівське:) Там фіг таке зробиш. Хоча тоді абсолютно не зрозуміла доцільність таких конструкцій в for, теж саме можна і while'ом зробити. В Паскалі ж зрозуміло, що for - не ітеративний цикл (не має можливості обчислення наближення до деякого значення), а тут в нього все, що завгодно можна запхати. Подивився асемблерний вивід обох варіантів у С і побачив, що і там і там використовується порівняння і умовний перехід у будь-якому випадку. Так що, дійсно, використання for чи while ніякої зміни в швидкодії не дасть, а при увімкненій оптимізації тим більш.
-
Ой, чур мене, STL:)
навіщо "чур"? хоч деякі ідеї в сучасному с++ досить складні, але для професійного програмування іх бажано знати :) а то так і залишишся на 15 років в минулому.
Хоча тоді абсолютно не зрозуміла доцільність таких конструкцій в for, теж саме можна і while'ом зробити.
можно назвати то синтаксичним оверхедом :) але просто зручніше мати такий оператор for, його звичайно можно зімітувати через while, але якщо for сприймається як одна синтаксична конструкція, то анологічний while як 2 - ініціалізація, зміна зміної по якій то все ітерується, перевірка умову і при цьому перші дві конструкції не прив"язані до конкретного місця в коді, відповідно читатися і супортитися такий код буде важче.
-
Отже "...маємо шо маємо...".
Я трішки помилився у своїх розрахунках. Насправді ітерацій не мільйон, а мільярд ::) .
Шматок коду, що тестувався, виглядає так:
//for(i=0;i<BreaksNumber;i++){
i=0;while (i++<BreaksNumber){
n[0]=i*d;
n[1]=i*h;
a=a0+n[0]+n[1];
b=a+d;
if (xz > a && xz < b){
xz1=xz0*z1*x_z0;
yz1=yz0*z1*y_z0;
fprintf(outfile,"%lf %lf\n",xz1,yz1);
}
}
компілювалося два рази - один з for, інший з while... ... gcc з опцієй -mmmx... ... ніяких -о чи -О нема. ....Всі змінні за виключенням і та BreaksNumber (unsigned long) мають тип double. Ніяких конструкторів, деструкторів, qt, gtk, tcl, та інше нема -- звичайний С. (Я себе професійним програмістом не вважаю ::) )
Комп'ютер - celeron tualatin 1300 MHz 256 Mb. ...зараз подивлюсь... ...Calibrating delay loop... 2580.48 BogoMIPS...
Під час запуску програм нічого такого неробилося. Навіть мишу не рухав. Запуски програм проводились по два рази (для статистики ;) ).
Результати:
for:
real 1m18.192s (+- 0.1s*)
user 1m17.421s (+- 0.1s)
sys 0m0.521s (+- 0.01s)
while:
real 1m17.724s (+- 0.1s)
user 1m16.974s (+- 0.1s)
sys 0m0.513s (+-0.01s)
*приблизно, на око ::)
Ну-с, що маємо?
while виявляється випереджає for. Хоча і на якісь 0.3 сик., і це на мільярд ітерацій.
Отже приблизно на 10e-10 сик. на ітерацію 8-)
ps Привіт Пану MoD`y ;)
-
Найголовніше забув:
lpi@tx2000:~$ gcc --version
gcc (GCC) 3.3.5 (Debian 1:3.3.5-8)
Copyright (C) 2003 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.
lpi@tx2000:~$
-
навіщо "чур"? хоч деякі ідеї в сучасному с++ досить складні, але для професійного програмування іх бажано знати Усмішка а то так і залишишся на 15 років в минулому.
З STL я більш-менш розбираюсь, просто, коли подивився на його реалізацію мені погано стало:D Така складність реалізації заради простоти використання? Я не думаю, що це правильна ідея. Хоча це власне НМД.
for:
real 1m18.192s (+- 0.1s*)
user 1m17.421s (+- 0.1s)
sys 0m0.521s (+- 0.01s)
while:
real 1m17.724s (+- 0.1s)
user 1m16.974s (+- 0.1s)
sys 0m0.513s (+-0.01s)
Ой не вірю я, що так повільно... А той масив n вам же не потрібен ще десь за межами циклу, як і змінні a, b - можна було б обійтись і без них.
-
...while виявляється випереджає for. Хоча і на якісь 0.3 сек., і це на мільярд ітерацій.
Отже приблизно на 10e-10 сек. на ітерацію. Круто.
В межах похибки результати співпадають.. Особливо, якщо зважити на наявність fprintf -- хтозна, куди система записувала ваші дані в той чи інший момент часу...
-
Без a,b,n :-/
...if (xz < a(0)+i*d+i*h && xz > a(0)+(i+1)*d+i*h){...
операцій множеня тут більше. Чи може я вас неправильно зрозумів?...
Часу багато займає, бо програма обробляла текстовий файл 7.4 Мб, що складається з double цифр (там перед цим фрагментом ще fscanf є).
А взагалі з практичної точки зору це питання безглузде, бо програма не є якоюсь realtime, тому якщо вона буде рахувати на 0.3 с повільніше, то мені від цього "ні холодно, ні жарко" ;)
ps В ІПФ міста Суми maple деякі задачі по 10 годин рахує. Зараз керівництво замислюється про GRID (Це той, що Sun Miсrosystem розробляеться).
-
Дійсно, змінну а можна залишити;) Хоча, якщо швидкість для вас великого значення не має, то можете все це залишити задля зручності.
-
У програмі є цикл, що крутиться приблизно мільйон разів. Логічно зробити так, щоб одна ітерація займала найменеше часу. Який оператор швидкіший :D ? for чи while? Чи може вони однаково компілюються? Що порадите?
1. Зафіксувати перед циклом і після час і вивести й порівняти.
2. Скомпілювати елементарні цикли й глянути в дизасемблері, що він там накомпілював.
-
Чого в дизасемблері? gcc -S.
-
Тема мені нагадала про - залежність швидкості від положення кабелів (була така ржачна тема на ixbt) та від адреси у пам'яті (якийсь відомий баян). Для ржачного доведення цих твердженнь застосовано мабуть всі відомі пересічній людини науково-фантастичні спекуляції ;D
-
Колись від адреси в пам'яті швидкодія справді залежала.
З якогось дива інтелівські процесори звертались за парними адресами чи не в півтора рази швидше, ніж за непарними.
-
З якогось дива інтелівські процесори звертались за парними адресами чи не в півтора рази швидше, ніж за непарними.
Це через вирівнівання пам`яті. Якщо ви хочете парне слово, то ви його берете прямо з пам`яті, а якщо непарне, то все одно берете спочатку парне (а можливо і два), вирізаєте з них те, що вам потрібно, і тільки потім отримуєте.
Там спочатку теми була така репліка, мовляв ще спитайте, що швидше і++ чи ++і. Так от швидше ++і, тому, що не створюється проміжна копія. Різницю можна помітити навіть в int-ів, і чим вільший тип і, тим серйозніша різниці в швидкості