Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.86
mihalech19
3 / 3 / 2
Регистрация: 23.06.2014
Сообщений: 126
#1

If или switch().case. Что быстрее - C++

07.07.2014, 10:22. Просмотров 2263. Ответов 27
Метки нет (Все метки)

Есть два кода. Первый:
C++
1
2
3
4
5
6
if(a == 2)
a += 2;
if(a == 3)
a+= 3;
if(a == 4)
a+=4;
Второй:
C++
1
2
3
4
5
6
switch(a)
}
case 2: a += 2; break;
case 3: a+= 3; break;
case 4: a += 4; break;
}
Эти коды одинаковы по своим функциям, но какой же из них будет работать быстрее?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.07.2014, 10:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос If или switch().case. Что быстрее (C++):

switch case 1 ИЛИ 2 - C++
делаю разбор вводимых команд, некоторые обрабатываются похоже, команды однобуквенные, разбираю кейсом, но вот как сделать чтобы 1 блок...

case outside of switch ? Что за ошибка? - C++
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #pragma argsused ...

Что делают операторы switch/case - C++
что делают функции : switch ? case ?

Оптимальная конструкция switch-case-while / while-switch-case - C++
Имеется конструкция типа: switch() { case 1: while() { ... }

Статический хеш или switch-case/if-else для выбора - C++
Добрый день. Положим есть такой код:void parseByType(const QString &data, const QString &type) { if(type == "integer") { ...

Оптимизируется ли компилятором конструкция switch-case? Работа со строками через ID объекта или hash - C++
Добрый вечер, 1) Определён ли порядок выбора switch (согласно стандарта кажись неопределён, но все компиляторы я уверен в этом...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
DrOffset
7138 / 4279 / 964
Регистрация: 30.01.2014
Сообщений: 7,067
07.07.2014, 18:30 #16
Цитата Сообщение от Kukurudza Посмотреть сообщение
кейсы без брейков жесть какая-та имхо
Это ты еще duff device не видел

------
А вообще все эти рассуждения о скорости не имеют смысла без привязки к конкретному компилятору и его оптимизации. Если хочется адекватных оценок, то берем компилятор, конкретные ключи компиляции, смотрим ассемблер и делаем выводы. Все остальное от лукавого.
0
ValeryS
Модератор
6631 / 5039 / 466
Регистрация: 14.02.2011
Сообщений: 16,847
07.07.2014, 18:48 #17
Цитата Сообщение от mihalech19 Посмотреть сообщение
Эти коды одинаковы по своим функциям,
фиг вам посмотри что будет если во первом коде
a изначальна равна 2 в результате она будет равна 8
чего не наблюдается во втором коде
Цитата Сообщение от Kukurudza Посмотреть сообщение
свитч вроде в в ифы разворачивается, нэ?
при очень разреженном
при case 0 1 2 3 4
скорее всего switch превратится в таблицу переходов
у Evg в блоге была статья на эту тему
если найду кину ссылку

Добавлено через 1 минуту
Цитата Сообщение от Kukurudza Посмотреть сообщение
кейсы без брейков жесть какая-та имхо
очень даже распространенная практика "проваливания"
кстати в шарпе её кастрировали и приходится дублировать код

Добавлено через 3 минуты
вот ссылка
http://www.cyberforum.ru/blogs/18334/blog91.html
0
Kastaneda
Форумчанин
Эксперт С++
4653 / 2862 / 228
Регистрация: 12.12.2009
Сообщений: 7,271
Записей в блоге: 2
Завершенные тесты: 1
07.07.2014, 18:49 #18
Цитата Сообщение от ValeryS Посмотреть сообщение
очень даже распространенная практика "проваливания"
согласен, чаще всего приходится встречать такое
C++
1
2
3
4
5
6
case 1: 
case 2:
case 3:
case 4:
    // code
    break;
в gcc добавили удобную фишку Case Ranges, можно писать так
C++
1
2
3
4
5
6
case 1 ... 4:
    // code
 
// и даже так
case 'a' ... 'z' :
    // code
0
ValeryS
Модератор
6631 / 5039 / 466
Регистрация: 14.02.2011
Сообщений: 16,847
07.07.2014, 18:55 #19
Цитата Сообщение от Kastaneda Посмотреть сообщение
чаще всего приходится встречать такое
чаще да
но посмотри на код по ссылке

Напоследок хочется сказать, что на практике такими "дебильными" конструкциями пользуются очень и очень редко. На практике я пока только однажды встречал конструкцию, являющуюся вариацией алгоритма под названием Duff's device
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void send (int *to, const int *from, int count)
{
  int n = (count + 7) / 8;
  swith (count % 8)
  {
    case 0: do { *to++ = *from++;
    case 7:      *to++ = *from++;
    case 6:      *to++ = *from++;
    case 5:      *to++ = *from++;
    case 4:      *to++ = *from++;
    case 3:      *to++ = *from++;
    case 2:      *to++ = *from++;
    case 1:      *to++ = *from++;
            } while (--n > 0);
  }
}
кстати обсуждалась здесь
Что делает данный код и зачем такое кому-нибудь может понадобиться?

Добавлено через 2 минуты
Цитата Сообщение от Kastaneda Посмотреть сообщение
в gcc добавили удобную фишку Case Ranges, можно писать так
а если нужно вот так
C++
1
2
3
4
5
switch(n)
 {
   case 5:
   case 10:
   case 15:
то "фишкой" уже не обойдешься
0
RaiaNKnight
96 / 70 / 7
Регистрация: 29.06.2011
Сообщений: 465
Записей в блоге: 1
07.07.2014, 19:00 #20
Ещё неплохой способ "we need to go deeper":

Юзаем switch-case:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
movl    $4, -4(%rbp)      // int a = 4;
 
movl    -4(%rbp), %eax  //switch begin
cmpl    $3, %eax
je  .L3
cmpl    $4, %eax
je  .L4
cmpl    $2, %eax
jne .L2                   //switch end
 
addl    $2, -4(%rbp)     //1-й case
jmp .L2
                .L3:
addl    $3, -4(%rbp)     //2-й case
jmp .L2
                .L4:     
addl    $4, -4(%rbp)     //3-й case
nop
                .L2:
...


Юзаем if'ы:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
movl    $4, -4(%rbp)   // int a = 4;
 
cmpl    $2, -4(%rbp)   //1-й if begin
jne .L2
addl    $2, -4(%rbp)   //1-й if end
 
                .L2:
cmpl    $3, -4(%rbp)   //2-й if begin
jne .L3
addl    $3, -4(%rbp)   //2-й if end
 
                .L3:
cmpl    $4, -4(%rbp)   //3-й if begin
jne .L4
addl    $4, -4(%rbp)   //3-й if end


Компилятор GNU GCC C++ .

Особо разницы не заметите, разве что во 1-м случае используются прыжки je, а во 2-м - jne.
0
Kastaneda
Форумчанин
Эксперт С++
4653 / 2862 / 228
Регистрация: 12.12.2009
Сообщений: 7,271
Записей в блоге: 2
Завершенные тесты: 1
07.07.2014, 19:07 #21
Цитата Сообщение от RaiaNKnight Посмотреть сообщение
Компилятор GNU GCC C++ .
попробуй с -O0, -O1, -O2, -O3 и кейсов хотя бы штук 10 - 15. Разница будет.
0
RaiaNKnight
96 / 70 / 7
Регистрация: 29.06.2011
Сообщений: 465
Записей в блоге: 1
07.07.2014, 19:15 #22
Это понятно, на примере, который был дан выше разницы никакой.
0
ValeryS
Модератор
6631 / 5039 / 466
Регистрация: 14.02.2011
Сообщений: 16,847
07.07.2014, 19:20 #23
лень придумывать примеры
вот кусок дезасемблированой реальной программы

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
 cmp     ecx, 7                          ; switch 8 cases
ja      short loc_20495F                ; default
jmp     ds:off_204970[ecx*4]    
...................
 
off_204970 dd offset loc_2048F5  
                dd offset loc_2048F8 
                dd offset loc_204911
                dd offset loc_204916
                dd offset loc_20491B
                dd offset loc_20491B
                dd offset loc_2048FB
                dd offset loc_20490C
один из вариантов работы свитча
кучей сравнений и не пахнет

Добавлено через 2 минуты
Цитата Сообщение от RaiaNKnight Посмотреть сообщение
который был дан выше разницы никакой.
еще раз повторю? разница огромная
в первом случае при a=2 отработают два if
так что пример ТС некорректен для исследования
1
RaiaNKnight
96 / 70 / 7
Регистрация: 29.06.2011
Сообщений: 465
Записей в блоге: 1
07.07.2014, 19:25 #24
Цитата Сообщение от RaiaNKnight Посмотреть сообщение
Особо разницы не заметите, разве что во 1-м случае используются прыжки je, а во 2-м - jne.
Цитата Сообщение от RaiaNKnight Посмотреть сообщение
Это понятно, на примере, который был дан выше разницы никакой.

Не по теме:

Можно смотреть только листинг на asm, остальное некорректно

0
ValeryS
07.07.2014, 19:29
  #25

Не по теме:

Цитата Сообщение от Renji Посмотреть сообщение
Если внутре у ней неонка
тоже люблю "Сказку о тройке"

0
Martein
Оператор ЭВМ 6 разряда
673 / 84 / 13
Регистрация: 22.06.2014
Сообщений: 174
07.07.2014, 19:43 #26
Вот так выглядит код в дизассемблере для первого случая:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
0x401600                    push   ebp
0x401601  <+0x0001>         mov    ebp,esp
0x401603  <+0x0003>         and    esp,0xfffffff0
0x401606  <+0x0006>         sub    esp,0x10
0x401609  <+0x0009>         call   0x4020d0 <__main>
        8       int a;
        9       if(a == 2)
0x40160e  <+0x000e>         cmp    DWORD PTR [esp+0xc],0x2
0x401613  <+0x0013>         jne    0x40161a <main()+26>
        10      a += 2;
0x401615  <+0x0015>         add    DWORD PTR [esp+0xc],0x2
        11      if(a == 3)
0x40161a  <+0x001a>         cmp    DWORD PTR [esp+0xc],0x3
0x40161f  <+0x001f>         jne    0x401626 <main()+38>
        12      a+= 3;
0x401621  <+0x0021>         add    DWORD PTR [esp+0xc],0x3
        13      if(a == 4)
0x401626  <+0x0026>         cmp    DWORD PTR [esp+0xc],0x4
0x40162b  <+0x002b>         jne    0x401632 <main()+50>
        14      a+=4;
0x40162d  <+0x002d>         add    DWORD PTR [esp+0xc],0x4
        15  }
0x401632  <+0x0032>         mov    eax,0x0
0x401637  <+0x0037>         leave
0x401638  <+0x0038>         ret
И вот так он выглядит для второго случая:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
0x401600                    push   ebp
0x401601  <+0x0001>         mov    ebp,esp
0x401603  <+0x0003>         and    esp,0xfffffff0
0x401606  <+0x0006>         sub    esp,0x10
0x401609  <+0x0009>         call   0x4020d0 <__main>
        8       int a;
        9       switch(a)
0x40160e  <+0x000e>         mov    eax,DWORD PTR [esp+0xc]
0x401612  <+0x0012>         cmp    eax,0x3
0x401615  <+0x0015>         je     0x401628 <main()+40>
0x401617  <+0x0017>         cmp    eax,0x4
0x40161a  <+0x001a>         je     0x40162f <main()+47>
0x40161c  <+0x001c>         cmp    eax,0x2
0x40161f  <+0x001f>         jne    0x401635 <main()+53>
        10      {
        11      case 2: a += 2; break;
0x401621  <+0x0021>         add    DWORD PTR [esp+0xc],0x2
0x401626  <+0x0026>         jmp    0x401635 <main()+53>
        12      case 3: a+= 3; break;
0x401628  <+0x0028>         add    DWORD PTR [esp+0xc],0x3
0x40162d  <+0x002d>         jmp    0x401635 <main()+53>
        13      case 4: a += 4; break;
0x40162f  <+0x002f>         add    DWORD PTR [esp+0xc],0x4
0x401634  <+0x0034>         nop
        14      }
        15  }
0x401635  <+0x0035>         mov    eax,0x0
0x40163a  <+0x003a>         leave
0x40163b  <+0x003b>         ret
Код генерируется практически такой же, но в другой последовательности и для switch создаются дополнительные безусловные инструкции передачи управления JMP, что увеличивает слегка размер машинного кода и лишние такты процессорного времени. В первом случае вы просто сэкономите ровнёхонько 3 байта кода.

Добавлено через 9 минут
P.S. С другой стороны в блоках if сравнение значений происходит с ячейкой памяти ОЗУ, а в switch'e сравнения значений происходят с регистром EAX, что по теории быстрее на несколько тактов.
0
ValeryS
Модератор
6631 / 5039 / 466
Регистрация: 14.02.2011
Сообщений: 16,847
07.07.2014, 20:04 #27
Цитата Сообщение от Martein Посмотреть сообщение
Вот так выглядит код в дизассемблере для первого случая:
для чистоты эксперимента указывается компилятор,режим компиляции и степень оптимизации
по приведенным листингам могу сделать вывод что оптимизация на минимуме или вообще отсутствует
ибо при зверской оптимизации компилятор выбросил бы всю эту лабуду бессмысленную(результаты никуда не идут и нигде не используются ) и оставил бы что то типа
C++
1
2
3
4
int main()
{
return 0:
}


Добавлено через 1 минуту
Цитата Сообщение от Martein Посмотреть сообщение
push * ebp
0x401601 *<+0x0001> * * * * mov * *ebp,esp
0x401603 *<+0x0003> * * * * and * *esp,0xfffffff0
0x401606 *<+0x0006> * * * * sub * *esp,0x10
а это вообще говорит о компиляции в режиме debug
0
Renji
1916 / 1314 / 298
Регистрация: 05.06.2014
Сообщений: 3,757
07.07.2014, 20:28 #28
и для switch создаются дополнительные безусловные инструкции передачи управления JMP, что увеличивает слегка размер машинного кода и лишние такты процессорного времени.
С чего бы лишние такты будут? Во-первых, последовательный код будет распихан на несколько работающих параллельно конвейеров. Пока mov может выполняться на конвейере А, ему как-то пофиг что творится на конвейере Б. Хоть десяток jmp. Во-вторых, команды скорее всего будут перетасованы как удобно процессору, а не как написал программист (внеочередное исполнение). А если процессор напорется на переход, он включит Вангу и скажет "за jmp прозреваю я mov!" (предсказание переходов). И продолжит исполнять команды не по порядку. После всех этих шаманств jmp едва ли хоть кого-то замедлит.

Другое дело что на je встроенный в процессор хрустальный шар часто ошибается с предсказанием направления перехода и половина выполненных не по порядку вычислений идет в помойку. Поэтому je действительно может знатно подгадить производительности.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.07.2014, 20:28
Привет! Вот еще темы с ответами:

Может ли значение метки case в операторе switch быть числовым отрезком, или только константой? - C++
Например, в Pascal возможна запись: ... Case a of 0..15: Write( a+7 ); ... Возможно ли аналогичная запись в c++? или...

Switch case внутри switch case - C++
Привет всем! Нужна помощь. Пишу калькулятор с консольным меню. Так вот, используется цикл while, внутри которого у меня switch...

switch-case, как писать в самом case - C++
Такс дело вот в чём,прога работает всё хорошо,вот только мне не нравится как записваю страны в кейсе,можно ли каким-нибудь образом писать в...

Что быстрее: i++ или ++i ? - C++
Только что прочитала в интернете, что префиксный итератор быстрее, чем постфиксный. Так ли это? Если так и если в С++ все есть обьект, то...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
07.07.2014, 20:28
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru