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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 35, средняя оценка - 4.74
FiloXSee
19 / 10 / 0
Регистрация: 01.07.2011
Сообщений: 25
#1

Методы оптимизации кода - C++

01.07.2011, 07:48. Просмотров 4683. Ответов 52
Метки нет (Все метки)

Написал статью по оптимизации кода на С++. Ее можно почитать тут:
[ссылка удалена]

А вы какие еще способы оптимизации кода знаете? (я не говорю про оптимизацию алгоритмов. Речь идет про код вообще)

 Комментарий модератора 
Ссылки на сторонние ресурсы у нас и так не приветствуются, а уж битые и подавно...
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.07.2011, 07:48
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Методы оптимизации кода (C++):

Методы оптимизации - C++
Здравствуйте, прошу помочь,кто может написать программу для решения задачи используя 2 метода ?1)Метод золотого сечения 2)Метод...

Курсовая. Методы оптимизации - C++
http://www.cyberforum.ru/attachments/402404d1400795723 Помогите чем сможете Заранее спасибо

Методы оптимизации памяти - C++
Написал статью по оптимизации памяти в программах на С++. Ее можно почитать тут: http://itw66.ru/blog/c_plus_plus/491.html А какие...

Методы Оптимизации: Метод параллельных касательных - нужен алгоритм - C++
Здравствуйте. Помогите пожалуйста с составлением алгоритма по методу параллельных касательных. Пытался читать литературу, но там алгоритмы...

Просмотр кода после оптимизации компилятора - C++
Здравствуйте! Известно, что компилятор оптимизирует код. А можно ли посмотреть оптимизированный код до того, как он будет переведен в...

Объяснить нюансы оптимизации заданного фрагмента кода - C++
Наткнулся на статью по оптимизации кода на C++http://itw66.ru/blog/c_plus_plus/13.html]ссылка Есть там 10-й пункт: SomeClass* p; -...

52
ValeryLaptev
Эксперт С++
1042 / 821 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
01.07.2011, 17:32 #31
pito211, еще надо указать с какими ключами компилятора все транслировалось. На каком уровне опимизации
0
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
01.07.2011, 17:48 #32
/Od .
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.07.2011, 17:51 #33
У меня GCC примерно то же самое выдал с -O3 (с другими не пробовал) попутно разбавив код установкой регистров esi, edi и eax (перед вызовом printf).
Но что толку их сравнивать, если они разный результат дают...
0
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
01.07.2011, 17:57 #34
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
    x = (a >= b ? -1 : 0);
002C14D0  mov         eax,dword ptr [a] 
002C14D3  xor         ecx,ecx 
002C14D5  cmp         eax,dword ptr [b] 
002C14D8  setl        cl   
002C14DB  sub         ecx,1 
002C14DE  mov         dword ptr [x],ecx 
    y = (b - a) >> 31;
002C14E1  mov         eax,dword ptr [b] 
002C14E4  sub         eax,dword ptr [a] 
002C14E7  sar         eax,1Fh 
002C14EA  mov         dword ptr [y],eax
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.07.2011, 18:00 #35
А вот, кстати, цитата из стандарта C++ по поводу сдвига вправо (п.5.8.3)
The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a
signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided
by the quantity 2 raised to the power E2. If E1 has a signed type and a negative value, the resulting value
is implementation-defined.
Так что арифметического сдвига никто не обещал. Как и логического, впрочем.
0
voral
490 / 470 / 79
Регистрация: 16.03.2008
Сообщений: 2,219
01.07.2011, 18:09 #36
Цитата Сообщение от grizlik78 Посмотреть сообщение
У меня GCC примерно то же самое выдал с -O3 (с другими не пробовал) попутно разбавив код установкой регистров esi, edi и eax (перед вызовом printf).
Но что толку их сравнивать, если они разный результат дают...
Вы под линуксом?
Подскажите как увидеть вот в таком формате то что получилось полсе компиляции - вчера gdb мучал, что то видно не нашел.....
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.07.2011, 18:15 #37
В таком формате не знаю (т.е. в gdb могу посмотреть), но GCC может не удалять ассемблерный файл, если использовать ключ --save-temps
Ну а если адреса нужны, то сейчас погляжу. Кажись objdump умел ещё дизассемблировать.

Добавлено через 1 минуту
Bash
1
objdump -d a.out
Добавлено через 2 минуты
В gdb
Код
disassemble main
1
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
01.07.2011, 18:19 #38
Цитата Сообщение от grizlik78 Посмотреть сообщение
А вот, кстати, цитата из стандарта C++ по поводу сдвига вправо (п.5.8.3)

Так что арифметического сдвига никто не обещал. Как и логического, впрочем.
возьму на заметку, а как gcc реагирует на такую конструкцию?
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.07.2011, 18:21 #39
Цитата Сообщение от pito211 Посмотреть сообщение
возьму на заметку, а как gcc реагирует на такую конструкцию?
Арифметически Я думаю имелись в виду возможности процессора. Не все (учитывая МК) умеют арифметический сдвиг. Но всё-равно явно никто ничего не обещал.
0
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
01.07.2011, 18:23 #40
извиняюсь заранее за тупой вопрос, что значит абревиатура МК?
0
grizlik78
Эксперт С++
1966 / 1459 / 120
Регистрация: 29.05.2011
Сообщений: 3,019
01.07.2011, 21:08 #41
микроконтроллеры

Добавлено через 2 часа 44 минуты
Цитата Сообщение от FiloXSee Посмотреть сообщение
Да, видимо там не очень удачный комментарий. Видимо комментатор там имел в виду, что нужно выносить все сложные вычисления из части условия в раздел объявления переменных, чтобы вычислять верхний предел один раз.
Со strlen() пример действительно не совсем удачный.
Касательно же циклов здесь есть гораздо более важный момент: очень желательно, чтобы к моменту начала цикла было бы известно точное количество итераций (даже вычисленное в рантайме). Это даст компилятору шанс развернуть цикл и использовать векторизацию (SIMD).
Например из кода
C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
int main()
{
    unsigned len, i, sum = 0;
    char s[1024];
    scanf("%s",s);
    scanf("%u",&len);
    for (i = 0; s[i]; ++i) /* неизвестно сколько раз */
        sum += s[i];
    printf("%d\n", sum);
    return 0;
}
gcc -O3 на x86_64 делает такой ассемблерный (извините за AT&T ) между scanf и printf
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
    call    scanf
    movzbl  16(%rsp), %eax
    testb   %al, %al
    je  .L5
    addq    $1, %rbx
    xorl    %edx, %edx
    .p2align 4,,10
    .p2align 3
.L3:
    movsbl  %al, %eax
    addl    %eax, %edx
    movzbl  (%rbx), %eax
    addq    $1, %rbx
    testb   %al, %al
    jne .L3
.L2:
    xorl    %eax, %eax
    movl    $.LC2, %esi
    movl    $1, %edi
    call    __printf_chk
; .................
 
.L5:
    .cfi_restore_state
    xorl    %edx, %edx
    jmp .L2
Тогда как из кода
C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
int main()
{
    unsigned len, i, sum = 0;
    char s[1024];
    scanf("%s",s);
    scanf("%u",&len);
    for (i = 0; i < len; ++i) /* ровно len раз */
        sum += s[i];
    printf("%d\n", sum);
    return 0;
}
получается это:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    call    scanf
    movl    28(%rsp), %esi
    testl   %esi, %esi
    je  .L8
    movl    %esi, %ecx
    shrl    $4, %ecx
    movl    %ecx, %eax
    sall    $4, %eax
    cmpl    $15, %esi
    jbe .L9
    testl   %eax, %eax
    je  .L9
    pxor    %xmm0, %xmm0
    xorl    %edx, %edx
    pxor    %xmm6, %xmm6
    pxor    %xmm4, %xmm4
    .p2align 4,,10
    .p2align 3
.L4:
    movdqa  (%rbx), %xmm1
    addl    $1, %edx
    movdqa  %xmm6, %xmm3
    addq    $16, %rbx
    movdqa  %xmm1, %xmm2
    cmpl    %edx, %ecx
    pcmpgtb %xmm1, %xmm3
    punpcklbw   %xmm3, %xmm2
    punpckhbw   %xmm3, %xmm1
    movdqa  %xmm4, %xmm3
    movdqa  %xmm2, %xmm5
    pcmpgtw %xmm2, %xmm3
    punpckhwd   %xmm3, %xmm2
    punpcklwd   %xmm3, %xmm5
    movdqa  %xmm1, %xmm3
    paddd   %xmm5, %xmm0
    paddd   %xmm2, %xmm0
    movdqa  %xmm4, %xmm2
    pcmpgtw %xmm1, %xmm2
    punpcklwd   %xmm2, %xmm3
    punpckhwd   %xmm2, %xmm1
    paddd   %xmm3, %xmm0
    paddd   %xmm1, %xmm0
    ja  .L4
    movdqa  %xmm0, %xmm1
    cmpl    %eax, %esi
    psrldq  $8, %xmm1
    paddd   %xmm1, %xmm0
    movdqa  %xmm0, %xmm1
    psrldq  $4, %xmm1
    paddd   %xmm1, %xmm0
    movd    %xmm0, 12(%rsp)
    movl    12(%rsp), %edx
    je  .L2
    .p2align 4,,10
    .p2align 3
.L10:
    mov %eax, %ecx
    addl    $1, %eax
    movsbl  32(%rsp,%rcx), %ecx
    addl    %ecx, %edx
    cmpl    %eax, %esi
    ja  .L10
.L2:
    xorl    %eax, %eax
    movl    $.LC2, %esi
    movl    $1, %edi
    call    __printf_chk
; .................
 
.L8:
    .cfi_restore_state
    xorl    %edx, %edx
    jmp .L2
.L9:
    xorl    %edx, %edx
    xorl    %eax, %eax
    .p2align 4,,2
    jmp .L10
что на длинных циклах реально должно получиться эффективнее (считаем что данные в кэше) за счёт активного использования SSE и нечастых проверок с переходами.
2
FiloXSee
19 / 10 / 0
Регистрация: 01.07.2011
Сообщений: 25
29.12.2011, 08:56  [ТС] #42
Мной написаны еще несколько статей по написанию эффективного кода. Надеюсь они будут вам полезны:
http://itw66.ru/blog/c_plus_plus/571.html - Эффективный код на С++
http://itw66.ru/blog/c_plus_plus/491.html - Методы оптимизации памяти
0
fasked
Эксперт С++
4948 / 2528 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
29.12.2011, 09:17 #43
следующее очень плохо:
C
1
2
3
4
5
6
7
8
9
10
int func( int index )
{
   switch( index )
  {
     case 0 : return 10; 
     case 1 : return 20;
..
     case .. :
  }
}
гораздо лучше:
C
1
2
3
4
5
int func( int index )
{
   static int array[] = { 10, 20, ...};
   return array[ index ];
}
Если говорить именно про оптимизацию, то данный код одинаков. Конструкция switch с небольшими промежутками в case, а в данном случае это так и есть (case 0, case 1, case 2 etc) раскрывается в точно такую же таблицу и время доступа будет О(1).
1
res
56 / 9 / 1
Регистрация: 05.04.2010
Сообщений: 143
29.12.2011, 09:28 #44
Цитата Сообщение от FiloXSee Посмотреть сообщение
Мной написаны еще несколько статей по написанию эффективного кода. Надеюсь они будут вам полезны:
http://itw66.ru/blog/c_plus_plus/571.html - Эффективный код на С++
http://itw66.ru/blog/c_plus_plus/491.html - Методы оптимизации памяти
/facepalm.:cofee2:
0
fasked
Эксперт С++
4948 / 2528 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
29.12.2011, 09:34 #45
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Используйте список инициализации конструктора, вместо присвоения значений в его теле. Так поля будут инициализироваться один раз.
Пишите так:
C++
1
2
3
4
5
SomeClass::SomeClass( int val1, int val2 )
   : m_val1( val1 )
   , m_val2( val2 )
{
}
Вместо:
C++
1
2
3
4
5
SomeClass::SomeClass( int val1, int val2 )
{
   m_val1 = val1;
   m_val2 = val2;
}
А во втором случае типа два раза?

Не правильный вариант выделения памяти:
Граммар наци негодуют.

Заведите себе подобные типы и всегда учитывайте, сколько занимают ваши переменные в памяти. Это поможет легче учитывать пункт 6.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 8 bit
typedef unsigned char           u8;
typedef signed   char           i8;
 
// 16 bit
typedef unsigned short          u16;
typedef signed   short          i16;
 
// 32 bit
typedef unsigned int            u32;
typedef signed   int            i32;
 
// 64 bit
typedef unsigned long long      u64;
typedef signed   long long      i64;
 
// floats
typedef float                   f32;
typedef double                  f64;
Стандарт языка не гарантирует размер типов, то есть не факт, что int - 32-битный и т.д.. Кроме того есть заголовочный файл stdint.h, в котором объявлены синонимы целочисленных типов с гарантированной шириной:
The following types are required:
int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t
В целом серьезно разбирать Вашу статью лениво. Она уныла.
5
29.12.2011, 09:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.12.2011, 09:34
Привет! Вот еще темы с ответами:

Рекомендации по оптимизации/ускорению кода и памяти, разбор ключей, профилирование приложений в VS и не только - C++
Вечер добрый форум, у меня на данный момент VS2010. Я так понимаю настройки сохраняется только для одного проекта. У меня по...

Дублирование кода и константные методы - C++
Есть метод method возвращающий ссылку на внутреннее значение объекта. Существует в двух вариантах - константный и обычный. Константная...

Методы защиты данных от записи во время выполнения участка кода? - C++
День добрый, форумчане. Вводные данные: - Весь свой код строю на работе с указателями. - Потоки пока не использую - Linux, gcc...

Разработать классы для описанных ниже объектов. Включить в класс методы set (…), get (…), show (…). Определить другие методы - C++
Разработать классы для описанных ниже объектов. Включить в класс методы set (…), get (…), show (…). Определить другие методы Abiturient:...


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

Или воспользуйтесь поиском по форуму:
45
Ответ Создать тему
Опции темы

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