Автор Гілка: Швидкодія оператора ++.  (Прочитано 3013 раз)

Відсутній Markus

  • Дописувач
  • **
  • дописів: 79
  • Карма: +0/-0
  • Програматор
Доброго вечора усім!
Сьогодні хочу запитати шановне панство про наступне:
Усі хто програмує на С чи С++ знають про операцію інкремент - ++, і знають про різницю між записами: n++ і ++n. Я недавно був на співбесіді прийому на роботу в одну фірму і там розумні люди мені сказали, що ці операції відрізняються, також, швидкістю виконання, мовляв один виконується швидше за інший. Мені чогось невірилось і я вирішив вдома цю інформацію перевірити. Написав невеличкі дві програмки, які проводять сумування двома способами одна програма префіксним (++n), а друга постфіксним (n++), виміряв час виконання цих програм командою time перший запуск цих програм показав що лідирує (++n) (менший час виконання), після другого повторного запуску лідирував (n++), інколи випадало що показувало однаковий час. Все ж було більше випадків що лідирувало все ж таки (++n). Але мені таки здається, що вони виконуються однаково, а час різний тому що система була по різному зайнята. Може комусь щось відомо, і бажає висловитись із цього приводу?
Чи потрібні Україні програмісти, які не знають англійської мови?

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Швидкодія оператора ++.
« Відповідей #1 : 2007-11-11 20:50:31 »
Теоретично при виконанні i++ створюється копія i, яку буде повернено як результат операції, тому ++i (де ця копія не створюється) має працювати швидше, але це все дуже компіляторозалежне.

Відсутній Cthulhu

  • Кореспондент
  • ***
  • дописів: 183
  • Карма: +0/-0
Re: Швидкодія оператора ++.
« Відповідей #2 : 2007-11-11 21:00:49 »
Теоретично при виконанні i++ створюється копія i, яку буде повернено як результат операції, тому ++i (де ця копія не створюється) має працювати швидше, але це все дуже компіляторозалежне.
Залежить, звичайно. Але якщо говорити про gcc, то такий ефект є.

2markus: а як ви заміряли? Протестуйте з stl-ними ітераторами, там сумнівів не має залишатись. З gcc преінкремент швидший.

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Швидкодія оператора ++.
« Відповідей #3 : 2007-11-11 21:41:24 »
Але перейматись цим не слід. У моїй тестовій програмі на -O0 воно дійсно зробило ту копію, але лише для випадку, коли значення дійсно повертається, тобто якщо написати
i++;
воно копію створювати не буде.
А на -O3 воно навіть цикл, в якому я його ганяв прибрало :(
Коли поклав туди printf, звісно, залишило, але вся різниця між ++i та i++ була в порядку команд.
Edit:
isbear@monstruozo:~$ echo $'#include\t<stdio.h>\nint main (void)\n{\nint i=2, b=10;\n\n\twhile (i<10000) {\n\t\tb += i++;\n\t\tprintf ("%d, %d", i, b);\n\t}\n\treturn 0;\n}\n' > t.c
isbear@monstruozo:~$ gcc -O3 -o to.s -S t.c
isbear@monstruozo:~$ sed -i -e 's/i++/++i/' t.c
isbear@monstruozo:~$ gcc -O3 -o tr.s -S t.c
isbear@monstruozo:~$ diff -u to.s tr.s
--- to.s        2007-11-11 22:05:57.000000000 +0200
+++ tr.s        2007-11-11 22:06:06.000000000 +0200
@@ -18,12 +18,12 @@
 .LCFI2:
        .p2align 4,,7
 .L2:
-       addl    %ebx, %ebp
        incl    %ebx
        xorl    %eax, %eax
-       movl    %ebp, %edx
-       movl    %ebx, %esi
        movl    $.LC0, %edi
+       addl    %ebx, %ebp
+       movl    %ebx, %esi
+       movl    %ebp, %edx
        call    printf
        cmpl    $10000, %ebx
        jne     .L2
isbear@monstruozo:~$
[/tt]
Edit:
Звісно, це все чистий C, про C++ - не знаю... Там ці оператори можуть бути перевизначені, отже можуть виконувати довільний код - а отже тоді треба розглядати ситуацію у контексті.

Судячи з бенчмарків, у перлі теж є такий ефект, але мізерний.
« Змінено: 2007-11-11 23:14:01 від ISBear »

Відсутній Cthulhu

  • Кореспондент
  • ***
  • дописів: 183
  • Карма: +0/-0
Re: Швидкодія оператора ++.
« Відповідей #4 : 2007-11-11 22:24:55 »
До речі, щодо операторів в C++.
/usr/include/c++/4.2.2/bits/stl_list.h:
     _Self&
      operator++()
      {
      _M_node = _M_node->_M_next;
      return *this;
      }

      _Self
      operator++(int)
      {
      _Self __tmp = *this;
      _M_node = _M_node->_M_next;
      return __tmp;
      }
Ку?

Відсутній Markus

  • Дописувач
  • **
  • дописів: 79
  • Карма: +0/-0
  • Програматор
Re: Швидкодія оператора ++.
« Відповідей #5 : 2007-11-12 00:24:18 »
Теоретично при виконанні i++ створюється копія i, яку буде повернено як результат операції, тому ++i (де ця копія не створюється) має працювати швидше, але це все дуже компіляторозалежне.
Залежить, звичайно. Але якщо говорити про gcc, то такий ефект є.

2markus: а як ви заміряли? Протестуйте з stl-ними ітераторами, там сумнівів не має залишатись. З gcc преінкремент швидший.

Запустив слідуюче:
Спочатку
time ./test_op1
А потім
time ./test_op2
Код на С в них (test_op1, test_op2) ідентичний, окрім того в одній робиться nCount++, а в іншій ++nCount, nCount типу int.
Чи потрібні Україні програмісти, які не знають англійської мови?

Відсутній Cthulhu

  • Кореспондент
  • ***
  • дописів: 183
  • Карма: +0/-0
Re: Швидкодія оператора ++.
« Відповідей #6 : 2007-11-12 00:42:38 »
Код на С в них (test_op1, test_op2) ідентичний, окрім того в одній робиться nCount++, а в іншій ++nCount, nCount типу int.
Ну, про C Михайло вже написав.

Відсутній BM

  • Кореспондент
  • ***
  • дописів: 162
  • Карма: +0/-0
  • SUSE Linux Products GmbH
Re: Швидкодія оператора ++.
« Відповідей #7 : 2007-11-12 14:17:53 »
Теоретично при виконанні i++ створюється копія i, яку буде повернено як результат операції, тому ++i (де ця копія не створюється) має працювати швидше, але це все дуже компіляторозалежне.
Залежить, звичайно. Але якщо говорити про gcc, то такий ефект є.

2markus: а як ви заміряли? Протестуйте з stl-ними ітераторами, там сумнівів не має залишатись. З gcc преінкремент швидший.

Але й автооптимізатор теж своє дає. Різні архітектури по-різному поводяться, на різних процах є post/pre-increment режим адресування для побудови стеків та ін. Ну й ще тут така цікава цитатка з C мануалу:
"The operations implied by the post-increment and post-decrement operators ++ and -- are performed at some time after the operand's former values are yielded and before the end of the expression, but not necessarily immediately after, or before other parts of the expression are evaluated."

<AnotherTopic>
Проте все-таки цікаво інше: на сучасних апаратах скільки воно виграє? Одну соту долю наносекунди? :) Хіба це допомагає продати більше копій софта й сильно задовільняє кінцевого юзвєря?.. Я-б, наприклад, зовсім інші запитання на співбесіді задавав навіть звичайним кодерам, які по-суті систему не дизайнять, а тільки вбивають код по вже готовій схемі. :)

А в Яндексі взагалі гасло: можеш і взагалі не вміти програмувати — навчимо. Важливо-ж зовсім інше...
</AnotherTopic>

« Змінено: 2007-11-12 14:18:36 від BM »

Відсутній Cthulhu

  • Кореспондент
  • ***
  • дописів: 183
  • Карма: +0/-0
Re: Швидкодія оператора ++.
« Відповідей #8 : 2007-11-12 14:39:34 »
Проте все-таки цікаво інше: на сучасних апаратах скільки воно виграє? Одну соту долю наносекунди? :) Хіба це допомагає продати більше копій софта й сильно задовільняє кінцевого юзвєря?..
Особисто я цим питанням ніколи не переймався, тим більше, існує купа інших способів вбити перформанс. Зараз всюди ліплю преінкремент - звичка виробилась, хоч і в дитинстві робив строго навпаки.

Я-б, наприклад, зовсім інші запитання на співбесіді задавав навіть звичайним кодерам, які по-суті систему не дизайнять, а тільки вбивають код по вже готовій схемі. :)

А в Яндексі взагалі гасло: можеш і взагалі не вміти програмувати — навчимо. Важливо-ж зовсім інше...
+1, що ще тут сказати...
« Змінено: 2007-11-12 14:39:51 від Cthulhu »