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

Производительность операций - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 55, средняя оценка - 4.71
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
20.11.2011, 06:34     Производительность операций #1
Не уверен в своих силах для самостоятельной оценки сабжа. Где можно найти информацию о производительности стандартных операций с++ (гуглением не справился, нашел только сравнение реализации на с++, джаве и на нескольких интерпретируемых языках)?
То есть интересует информация плана << : * как 1:15 или <= : == как 25:24... То есть, чрезвычайно интересно знать, какие операции выбирать если есть альтернатива.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 16:31  [ТС]     Производительность операций #2
Мою тему просмотрело 39 человек и всем нечего было сказать. Я решился сам.
C++
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#include<iostream>
#include<vector>
 
int main()
{
    setlocale( LC_ALL, "Russian" );
    std::cout.width(5);
 
    typedef std::vector<double> proportions;
    proportions rezults;
    for (int q = 0; q != 200; ++q) { rezults.push_back(0); }
    unsigned long long iterationCounter = 0;
 
    while ( true || false )
    {
        int a, b, c, i = 0;
        
        //Инициализация и присваивание
        __asm
        {
            rdtsc
            mov a, eax
        }
        double n1;
        n1 = 0x55e100;
        __asm
        {
            rdtsc
            mov b, eax
        }
        double n2 = 0x55e100;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        //Префиксный или постфиксный инткримент
        int e = 0;
        __asm
        {
            rdtsc
            mov a, eax
        }
        e++;
        __asm
        {
            rdtsc
            mov b, eax
        }
        ++e;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        /*Насколько быстрее разименование указателя на double, чем итератора std::vector<double>*/
        std::vector<double> arr(1);
        arr[0] = asin(static_cast<double>(1)) * 2;//pi
        std::vector<double>::iterator it = arr.begin();
        double* val = new double;
        *val = arr[0];
        __asm
        {
            rdtsc
            mov a, eax
        }
        *it;
        __asm
        {
            rdtsc
            mov b, eax
        }
        *val;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        /*Обращение к элементу вектора и массива*/
        __asm
        {
            rdtsc
            mov a, eax
        }
        arr[0];
        __asm
        {
            rdtsc
            mov b, eax
        }
        val[0];
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        //Сложение и умножение целочисленно
        int x = 23, y = 1234;
        __asm
        {
            rdtsc
            mov a, eax
        }
        x *= y;
        __asm
        {
            rdtsc
            mov b, eax
        }
        x += y;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        //Вещественно
        double f = log(static_cast<double>(55e12)), g = sqrt(f);
        __asm
        {
            rdtsc
            mov a, eax
        }
        f *= g;
        __asm
        {
            rdtsc
            mov b, eax
        }
        f += g;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
        
        //Извлечение корня и умножение вещественно
        __asm
        {
            rdtsc
            mov a, eax
        }
        sqrt(f);
        __asm
        {
            rdtsc
            mov b, eax
        }
        f *= g;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
 
        //Разименование или обращение по индексу для массива
        __asm
        {
            rdtsc
            mov a, eax
        }
        val[0];
        __asm
        {
            rdtsc
            mov b, eax
        }
        *val;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        
        //Разименование или обращение по индексу для вектора
        __asm
        {
            rdtsc
            mov a, eax
        }
        arr[0];
        __asm
        {
            rdtsc
            mov b, eax
        }
        *it;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        //Меньше или неравно
        __asm
        {
            rdtsc
            mov a, eax
        }
        x < y;
        __asm
        {
            rdtsc
            mov b, eax
        }
        x != y;
        __asm
        {
            rdtsc
            mov c, eax
        }
        rezults[i] = ( rezults[i] * iterationCounter + static_cast<double>( b - a ) / ( c - b ) ) / ( iterationCounter + 1 );
        ++i;
 
        
        if( !(++iterationCounter % 10000) )
        {
            std::cout << "Усреднение №" << iterationCounter << ":\n";
            std::cout << "Инициализация в " << rezults[0] << " раз быстрее, чем обявление+присвоение.\n";
            std::cout << "Префиксный инткримент в " << rezults[1] << " раз быстрее, чем постфиксный.\n";
            std::cout << "Разименование указателя в " << rezults[2] << " раз быстрее, чем итератора.\n";
            std::cout << "Обращение к элементу массива в " << rezults[3] << " раз быстрее, чем к элементу вектора.\n";
            std::cout << "Целочисленное сложение в " << rezults[4] << " раз быстрее, чем умножение.\n";
            std::cout << "Вещественное сложение в " << rezults[5] << " раз быстрее, чем умножение.\n";
            std::cout << "Умнжение в " << rezults[5] << " раз быстрее, чем извлечение корня.\n";
            std::cout << "Указатель в " << rezults[6] << " раз быстрее, чем индекс.\n";
            std::cout << "Итератор в " << rezults[7] << " раз быстрее, чем индекс.\n";
            std::cout << "Неравно в " << rezults[8] << " раз быстрее, чем меньше.\n";
        }
    }
}
Выдал у меня результаты
Код
Усреднение №2620000:
Инициализация в 1.09377 раз быстрее, чем обявление+присвоение.
Префиксный инткримент в 0.998926 раз быстрее, чем постфиксный.
Разименование указателя в 19.9195 раз быстрее, чем итератора.
Обращение к элементу массива в 8.17944 раз быстрее, чем к элементу вектора.
Целочисленное сложение в 1.02781 раз быстрее, чем умножение.
Вещественное сложение в 2.49602 раз быстрее, чем умножение.
Умнжение в 2.49602 раз быстрее, чем извлечение корня.
Указатель в 1.18523 раз быстрее, чем индекс.
Итератор в 1.04466 раз быстрее, чем индекс.
Неравно в 0.424205 раз быстрее, чем меньше.
в Visual C++ 2010, со стандартными настройками оптимизации (не менял, потому, что не знаю что значат настройки). Прошу прокомментировать объективность моего теста. Только умоляю, с премерами. Т. е. если вы говорите, что я что-либо определил неверно (скажем, отключенная оптимизация критически повлияла на скорость обращения к элементу вектора), укажите точно, что не верно (в случае с вектором, скажите, какой именно параметр оптимизации нужно включить).
Я уверен, что тема интересна не только мне, и буду рад, если кто-то проявит интерес и дополнит мой список сравнений своим.
Очень надеюсь, что найдётся человек, имеющий хорошее понятие об оптимизации в какой-либо среде разработки, и сможет сформулировать правило написания объективного теста сабжа.
Bers
Заблокирован
21.11.2011, 16:39     Производительность операций #3
rdtsc нельзя доверять на многоядерных камнях
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 16:42  [ТС]     Производительность операций #4
Во время правки, обнаружил явное свидетельство, что в таком виде результат не верен: если поменять местами порядок выполнения в последнем тесте( x < y; и x != y; ), не изменится ничего. Хотя, это можно объяснить тем, что операции выполняются одинаково долго, сопоставимо с затратами на засечение времени.

Добавлено через 1 минуту
Да, кстати. У меня sony Vaio с intel core i3 по моему. 4 ядра (виртуальное удвоение)

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
rdtsc нельзя доверять на многоядерных камнях
Возможно, именно из-за этого у меня при небольшом количестве проходов (менее десяти) результаты сильно другие... Да и вообще, постоянно разные. В идеальном тесте соотношение должно быть постоянным.
Сыроежка
Заблокирован
21.11.2011, 16:43     Производительность операций #5
Не стал разбираться в вашем коде, так как сразу столкнулся с вызывающими вопросы конструкциями.

Например, в С++ (если имеется в виду стандарт 2003, как в 2011 я не знаю) нет такого типа, как long long. Или такая вычурная конструкция, как while ( true || false ). Очевидно, что true || false всегда равно true , поэтому почему бы просто не написать while ( true ), если вы имеете в виду бесконечный цикл.

Кроме того ваши выводы по поводу постинкремента и прединкоремента некорректные, так как обычно если значение постинкремента не присваивается другой переменной, то для функдаментальных типов компилятор генерирует один и тот же код для прединкремента и постинкремента. Если же речь заходит о пользовательских типах, то тем более ваш вывод некорректен, так как все зависит от сложности реализации пользовательских типов, и нельзя с определенностью указать разницу во времени исполнения.

То есть поднятый вами вопрос и то, как вы подощли к его решению, не представляет никакого интереса для профессиональных программистов..
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.11.2011, 16:45     Производительность операций #6
А еще советую собрать программу в режиме релиза, врубить -O3 и попробовать еще раз.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 16:50  [ТС]     Производительность операций #7
процессор Core i5 2530 МГц в яндексмаркете написано

Добавлено через 3 минуты
Цитата Сообщение от Сыроежка Посмотреть сообщение
не представляет никакого интереса для профессиональных программистов..
Уходи из моего топика в раздел для профессионалов, злой человек. У страуструпа, в его великом толмуде написано, что префиксный лучше. Как вы упомянули, для вас очевидно, что компилятор учтёт, что для встроенного типа в данном контектсе разницы нет, и сгенерирует одинаковый код. Мне же, такие вещи, не дают покоя день и ночь. Я мало читал и не уверен, поведёт ли себя компилятор безупречно в таком контексте.
Сыроежка
Заблокирован
21.11.2011, 16:53     Производительность операций #8
Никаких проблем. Могут все уйти из вашего топика, если мнения других вас не интересуют!
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
21.11.2011, 16:54     Производительность операций #9
Цитата Сообщение от CEBEP Посмотреть сообщение
что префиксный лучше.
Эстетика это все, а не борьба за производительность.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:00  [ТС]     Производительность операций #10
Цитата Сообщение от ForEveR Посмотреть сообщение
А еще советую собрать программу в режиме релиза, врубить -O3 и попробовать еще раз.
Переключил на релиз, результаты изменились! Что такое -ОЗ, не понял... что это?
Код
Усреднение №2900000:
Инициализация в 1.22925 раз быстрее, чем обявление+присвоение.
Префиксный инткримент в 4.56375 раз быстрее, чем постфиксный.
Разименование указателя в 1.07129 раз быстрее, чем итератора.
Обращение к элементу массива в 2.59468 раз быстрее, чем к элементу вектора.
Целочисленное сложение в 2.56498 раз быстрее, чем умножение.
Вещественное сложение в 2.54113 раз быстрее, чем умножение.
Умнжение в 2.54113 раз быстрее, чем извлечение корня.
Указатель в 2.53189 раз быстрее, чем индекс.
Итератор в 2.50638 раз быстрее, чем индекс.
Неравно в 2.58332 раз быстрее, чем меньше.
Цитата Сообщение от Сыроежка Посмотреть сообщение
компилятор генерирует один и тот же код
Посмотрите, для теста в текущем состоянии, префиксный вид работает быстрее вчетверо!

Добавлено через 2 минуты
Цитата Сообщение от fasked Посмотреть сообщение
а не борьба за производительность
Нет, там подробный коментайрий. префиксный в с++ выполняется до каких-либо других операций. таким образом не нужно заводить копию переменной. А при выполнении постфиксного инкремента/декремента создаётся копия переменной, передаваемая для остальных операций, а значение соответствующее идентификатору к которому применена операция меняется независимо от копии.

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
если мнения других вас не интересуют
Просто ваша бескомпромиссность не располагает. Ведь уже сейчас, я продемонстрировал, что ваше утверждение о инкрементах/декрементах не верно в абсолютном смысле.
LosAngeles
Заблокирован
21.11.2011, 17:04     Производительность операций #11
Цитата Сообщение от CEBEP Посмотреть сообщение
Посмотрите, для теста в текущем состоянии, префиксный вид работает быстрее вчетверо!
едва ли это так
Код
int e = 0;
                __asm
                {
                        rdtsc
010A1251  rdtsc  
                        mov a, eax
010A1253  mov         dword ptr [esp+1Ch],eax  
                }
                e++;
                __asm
                {
                        rdtsc
010A1257  rdtsc  
                        mov b, eax
010A1259  mov         dword ptr [esp+18h],eax  
                }
                ++e;
                __asm
                {
                        rdtsc
010A125D  rdtsc  
                        mov c, eax
010A125F  mov         dword ptr [esp+20h],eax  
                }
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
21.11.2011, 17:04     Производительность операций #12
Цитата Сообщение от CEBEP Посмотреть сообщение
Что такое -ОЗ, не понял... что это?
Максимальный уровень оптимизации.
Цитата Сообщение от CEBEP Посмотреть сообщение
Нет, там подробный коментайрий. префиксный в с++ выполняется до каких-либо других операций. таким образом не нужно заводить копию переменной. А при выполнении постфиксного инкремента/декремента создаётся копия переменной, передаваемая для остальных операций, а значение соответствующее идентификатору к которому применена операция меняется независимо от копии.
Современные компиляторы, как уже говорилось выше, будут поумнее многих программистов и в состоянии определить когда надо делать копию, а когда нет. Поэтому - исключительно эстетика.

Не по теме:

И не надо мне объяснять почему префиксный лучше, это лишнее

Сыроежка
Заблокирован
21.11.2011, 17:05     Производительность операций #13
Цитата Сообщение от CEBEP Посмотреть сообщение
Посмотрите, для теста в текущем состоянии, префиксный вид работает быстрее вчетверо!

Добавлено через 2 минуты

Нет, там подробный коментайрий. префиксный в с++ выполняется до каких-либо других операций. таким образом не нужно заводить копию переменной. А при выполнении постфиксного инкремента/декремента создаётся копия переменной, передаваемая для остальных операций, а значение соответствующее идентификатору к которому применена операция меняется независимо от копии.
Я вам уже все написал, только вы из-за своего гонора дилетанта не внимательно читаете, что вам пишут другие!
Повторю еще раз, если с первого раза до вас не доходит. Если результат посинкрементной операции для фундаментального типа не присваивается другой переменной, то компилятор генерирует один и тот же код для прединкремента и постинкремента.

Например, в следующих двух примерах никакой разницы нет

C++
1
2
for ( int i = 0; i < 10; i++ );
for ( int i = 0; i < 10; ++i );
Для этих двух строк компилятор генерирует один и тот же код. Поэтому польза от ваших тестов нулевая. Не проще ли сразу посмотреть, какой окд генерируется компилятором? Тем более, как я уже написал, если речь идет о пользовательсикх типах, то тем более ваши оценки не имеют смыса, так как все зависит от сложности реализации пользовательских типов.

Заранее предвижу вашу реакцию, так как дилетанты всегда агрессивны, поэтому убедительная просьба, перечитать мой ответ по крайнней мере два раза, прежде чем, что-то возражать.
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
21.11.2011, 17:08     Производительность операций #14
Цитата Сообщение от Сыроежка Посмотреть сообщение
Для этих двух строк компилятор генерирует один и тот же код.
А если выражаться точно, то никакого кода для этих двух примеров не генерируется
Paporotnik
383 / 227 / 7
Регистрация: 06.07.2011
Сообщений: 512
21.11.2011, 17:12     Производительность операций #15
имеется ввиду, что разница в производительности в большинстве случаев настолько несущественна с современными мощностями и компиляторами, что никакого отношения к серьезной оптимизации оно не имеет и чаще всего интересна из чистого любопытства. и когда пишется код, правильнее выбирать то, что очевидно в данной ситуации и наиболее понятно при чтении кода.

и вообще странное противопоставление сложения и умножения...

не проще сравнить ассемблерные команды операций для оценки производительности?
Сыроежка
Заблокирован
21.11.2011, 17:17     Производительность операций #16
Цитата Сообщение от fasked Посмотреть сообщение
А если выражаться точно, то никакого кода для этих двух примеров не генерируется
Не надо делать скоропалитеьных выводов! Это все зависит от компилятора и режима компиляции.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:20  [ТС]     Производительность операций #17
Цитата Сообщение от Сыроежка Посмотреть сообщение
Повторю еще раз,
Но ведь я же продемонстрировал, что в текущем состоянии мой код выдаёт результаты, расходящиеся с тем, что прогнозируете вы (кстати, я доверительно отнёсся к вашему посылу, ведь в первоначальном варианте результаты польностью ему соответствовали). Если расхождение есть, объясните, откуда оно а не говорите что сделает компилятор, если очевидно обратное.

Цитата Сообщение от Paporotnik Посмотреть сообщение
странное противопоставление сложения и умножения
Я недавно изучал алгоритм построения гладкой линии, в википедии был приведёт вариант реализации, тщательно избегавший операции умножения. Мне хотелось понять, насколько это оправданно.


Цитата Сообщение от fasked Посмотреть сообщение
Максимальный уровень оптимизации.
Боюсь, это приведёт к тому, что выполнение части моих операций будет отключено вовсе. Было бы хорошо добиться того, чтобы компилятор делал какую-то оптимизацию, скажем, по обращению к элементу вектора, но в то же время, не на столько грубую, чтобы отключать операции, в которых нет явной необходимости.

Цитата Сообщение от Paporotnik Посмотреть сообщение
разница в производительности в большинстве случаев настолько несущественна с современными мощностями и
Отказываюсь понимать, почему производительность кого-то не интересует. Если я планирую не уходить от разработки простых интерфейсов, возможно. Но по моей специальности (не програмирование), мне в ближайшее время придётся писать максимально эффективные коды (в частности, решение специфичных СЛАУ, не имеющих эффективной реализации в библиотеках типа boost).
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.11.2011, 17:22     Производительность операций #18
CEBEP, Точно не имеющих? http://www.boost.org/doc/libs/1_47_0.../doc/index.htm
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
21.11.2011, 17:24     Производительность операций #19
Цитата Сообщение от Сыроежка Посмотреть сообщение
Не надо делать скоропалитеьных выводов! Это все зависит от компилятора и режима компиляции.
В таком случае Ваш вывод о префиксном и постфиксном тоже скоропостижен
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.11.2011, 17:24     Производительность операций
Еще ссылки по теме:

Влияет ли на производительность C++
C++ Константы, геттеры/сеттеры и производительность
C++ Производительность CPU, КЕШ, многопоточность

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

Или воспользуйтесь поиском по форуму:
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:24  [ТС]     Производительность операций #20
Цитата Сообщение от ForEveR Посмотреть сообщение
Точно не имеющих?
зуб даю
Yandex
Объявления
21.11.2011, 17:24     Производительность операций
Ответ Создать тему
Опции темы

Текущее время: 20:24. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru