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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 55, средняя оценка - 4.71
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
20.11.2011, 06:34     Производительность операций #1
Не уверен в своих силах для самостоятельной оценки сабжа. Где можно найти информацию о производительности стандартных операций с++ (гуглением не справился, нашел только сравнение реализации на с++, джаве и на нескольких интерпретируемых языках)?
То есть интересует информация плана << : * как 1:15 или <= : == как 25:24... То есть, чрезвычайно интересно знать, какие операции выбирать если есть альтернатива.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Сыроежка
Заблокирован
21.11.2011, 17:29     Производительность операций #21
Цитата Сообщение от CEBEP Посмотреть сообщение
Но ведь я же продемонстрировал, что в текущем состоянии мой код выдаёт результаты, расходящиеся с тем, что прогнозируете вы (кстати, я доверительно отнёсся к вашему посылу, ведь в первоначальном варианте результаты польностью ему соответствовали). Если расхождение есть, объясните, откуда оно а не говорите что сделает компилятор, если очевидно обратное.
Всегда надо смотреть, какой объектный код генерирует компилятор. И если есть расхождение в генерируемом объектном коде для прединкремента и постинкремента, то определять причину, чем вызвано это расхождение. Как уже неоднократно я писал, если результат постинкремента для фундаментального типа не присваивается другому объекту, то компилятор обычно генерирует такой же код, как и для прединкремента.

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

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

Поэтому я и говорю, что для профессионалов ваш подход и ваши оценки не представяют инетреса. Они интересны лишь из любопытства для новичков, которые узнали, что существует разница между постинкрементом и прединкрементом и ринулиьс это сразу же проверять.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Paporotnik
383 / 227 / 7
Регистрация: 06.07.2011
Сообщений: 512
21.11.2011, 17:44     Производительность операций #22
Я недавно изучал алгоритм построения гладкой линии, в википедии был приведёт вариант реализации, тщательно избегавший операции умножения. Мне хотелось понять, насколько это оправданно.
да, умножение и деление затратные операции, их желательно избегать по возможности. и то, только в том случае, если ф-ция, где они имеют место быть, вызываются крайне часто и/или критично время работы и/или желательно выполнение на аппаратном уровне. к примеру, примитивные ф-ции компьютерной графики, которые подпадают под все требования.
а вот в инженерном расчете кривых в авиационном деле никто умножения не избегает. так как на фоне общих затрат производительности подобная оптимизация будет столь несущественна, что никак не окупит потраченное на нее время и возможное уменьшение точности расчетов.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:47  [ТС]     Производительность операций #23
Цитата Сообщение от Сыроежка Посмотреть сообщение
ринулиьс это сразу же проверять
На самом деле, префиксную и постфиксную форм я сравнивал просто для кучи. я люпблю написать что-нибудь типа
C
1
2
double k = *++currentPoint == '-' ? .1 : 10;
    ++currentPoint;
И мне хотелось знать, выйграл ли я что-то , от того что вынес смещение указателя в отдельню строку. В подобном же контексте мне были нитересны < и !=, часто приходится писать for(int i = 0; i != size; ++i), пока мой эксперимент показал, что именно такая запись работает быстрее всего (хотя надёжнее, хоть и не много, написать for(int i = 0; i < size; ++i). На самом деле, основной интерес для меня сейчас представляют контейнеры. Я часто встречал разные мнения о них. Кто-то ругал итераторы, кто-то наоборот, обращения по индексу. У меня на работе есть один умный и хороший специалист (выиграл всероссийскую олимпиаду по сопромату), который принципиально (не потому что лень изучить), не использует стандартные контейнеры а всегда пишет double* array = new double[length];, прекрасно понимая все минусы подхода, просто не хочет связываться. Я сейчас пишу разбор файла, в котором мне не обойтись без вектора ( я должен считать узлы геометрии объекта, не зная на этапе прочтения, сколько их. ). По этому я прикладываю усилия по изучению стандартных контейнеров, надеясь добиться такого кода на с++, который не уступал бы использованию указателей по производительности.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:47  [ТС]     Производительность операций #24
Цитата Сообщение от Paporotnik Посмотреть сообщение
умножения не избегает
У нас там есть реализация одна, в ней участвуют и умножение и даже одно извлечение корня, но ещё и очень много сложений и обращений к элементам массива массивов (x[i][j]). Вот меня интересовало, стоит ли переписать обращения по индексам в указатели, или это только трата времени, усложнение кода и ничтожный выигрыш. пока однозначно говорить не хочу, но считаю что переписать есть смысл.
Bers
Заблокирован
21.11.2011, 17:50     Производительность операций #25
Цитата Сообщение от CEBEP Посмотреть сообщение
double k = *++currentPoint == '-' ? .1 : 10;
* * * * ++currentPoint;
За такое по щам получить можно.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 17:54  [ТС]     Производительность операций #26
Я ожидал, что извлечение корня дольше чем умножение раз в 20 как минимум, а оказывается всего в 2,5. Это повод всё-таки переписать алгоритм.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
За такое по щам получить можно.
альтернатива -
C++
1
double k = *++currentPoint++ == '-' ? .1 : 10;
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.11.2011, 17:54     Производительность операций #27
CEBEP, Пишите на сях, если смотрите на крохи ускорения и хотите переписать алгоритм с индексной формы в форму указателей. А С++ не трогайте в этом случае.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 18:02  [ТС]     Производительность операций #28
Цитата Сообщение от Paporotnik Посмотреть сообщение
в инженерном расчете кривых в авиационном деле
у нас конечноэлементные и конечнообъёмные расчёты

Короче, по сабжу кто что может сказать? Как повысить объективность теста?
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
21.11.2011, 18:04     Производительность операций #29
Цитата Сообщение от CEBEP Посмотреть сообщение
альтернатива -
А за такое получить нужно
Цитата Сообщение от CEBEP Посмотреть сообщение
У меня на работе есть один умный и хороший специалист (выиграл всероссийскую олимпиаду по сопромату), который принципиально (не потому что лень изучить), не использует стандартные контейнеры а всегда пишет double* array = new double[length];, прекрасно понимая все минусы подхода, просто не хочет связываться
Хороший специалист в сопромате возможно, но не в программировании точно.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 18:07  [ТС]     Производительность операций #30
Цитата Сообщение от ForEveR Посмотреть сообщение
А С++ не трогайте в этом случае.
вот ко мне приходит файл,в котором хранятся переменные. причём стандарт файла такой, что в заголовке колличество переменных не указано. Чем выдумывать что-то для подсчёта переменных (пускай их немного, скажем 600-3000), разумнее воспользоватся вектором. Теперь мне надо решить, что с этим вектором делать, ведь я могу написать double* arr = &dat[0], что куда стрёмнее чем приведённый мною выше код с инкриментами и операцией условия, а могу разобраться с вектором и организовать код так, что переходить на сишные массивы не придётся.

Добавлено через 1 минуту
Цитата Сообщение от fasked Посмотреть сообщение
но не в программировании точно.
Ну вот и я так думаю. Если его мнение так сильно разнится с общепринятым то доверять ему не стоит. По этому и разбираюсь с контейнерами
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.11.2011, 18:08     Производительность операций #31
CEBEP, Скорость вектора в любом случае будет ниже, чем использование указателя (если конечно грамотно использовать).
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 18:11  [ТС]     Производительность операций #32
просто ещё на первом курсе написал парсер, он использовал стеки. Когда я перешел от стеков к массивам (просто выделил память под максимально высокий стэк), получил (зависело от контекста) прирост производительности в 80 раз. Ясно же, что если бы проблема решалась только так, то технологии с++ небыли бы настолько популярными. Но полагаться на произвол оптимизатора тоже страшно. Вот и изучаю. Сейчас если доведу написание теста до конца, ещё в IDE Qt запущу тест, разницу посмотрю...
LosAngeles
Заблокирован
21.11.2011, 18:11     Производительность операций #33
Цитата Сообщение от CEBEP Посмотреть сообщение
В подобном же контексте мне были нитересны < и !=, часто приходится писать for(int i = 0; i != size; ++i), пока мой эксперимент показал, что именно такая запись работает быстрее всего
этого не может быть, оба оператора реализуются одинакова, разница только в переходе, je быстрее jge работает?
Bers
Заблокирован
21.11.2011, 18:16     Производительность операций #34
Цитата Сообщение от fasked Посмотреть сообщение
double* array = new double[length];
В этой записи кроется угроза. Система, которая пестрит такими записями на самом верхнем уровне - по сути беззащитный ягненок, и может отказать в любой момент


Цитата Сообщение от CEBEP Посмотреть сообщение
Чем выдумывать что-то для подсчёта переменных (пускай их немного, скажем 600-3000), разумнее воспользоватся вектором.
"безопасное хранилище данных" в помощь

Добавлено через 4 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
CEBEP, Скорость вектора в любом случае будет ниже, чем использование указателя (если конечно грамотно использовать).
Что такое скорость вектора? Если имеется ввиду скорость доступа к элементам массива, ничто не мешает получать доступ к элементам посредством обычного указателя точно так же, как и при работе с обычными дин. массивами.
А если слегка подшаманить, можно подружить вектор с массивами на стеке. Для особо капризных случаев. Только вот.. в 99% случаев этого нафег не нужно.
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 18:16  [ТС]     Производительность операций #35
Цитата Сообщение от LosAngeles Посмотреть сообщение
je быстрее jge работает?
ну я тоже с кое-чем в тесте не согласен, это говорит что он или запущен или скомпилирован неверно. Если бы мы не отвлекались, а разбирались что исправить в проекте, возможно к 4 странице топа уже бы имели классный текст, с логически понятными результатами, сходящимися с теорией...
Сыроежка
Заблокирован
21.11.2011, 18:17     Производительность операций #36
Цитата Сообщение от CEBEP Посмотреть сообщение
На самом деле, префиксную и постфиксную форм я сравнивал просто для кучи. я люпблю написать что-нибудь типа
C
1
2
double k = *++currentPoint == '-' ? .1 : 10;
    ++currentPoint;
И мне хотелось знать, выйграл ли я что-то , от того что вынес смещение указателя в отдельню строку. В подобном же контексте мне были нитересны < и !=, часто приходится писать for(int i = 0; i != size; ++i), пока мой эксперимент показал, что именно такая запись работает быстрее всего (хотя надёжнее, хоть и не много, написать for(int i = 0; i < size; ++i). На самом деле, основной интерес для меня сейчас представляют контейнеры. Я часто встречал разные мнения о них. Кто-то ругал итераторы, кто-то наоборот, обращения по индексу. У меня на работе есть один умный и хороший специалист (выиграл всероссийскую олимпиаду по сопромату), который принципиально (не потому что лень изучить), не использует стандартные контейнеры а всегда пишет double* array = new double[length];, прекрасно понимая все минусы подхода, просто не хочет связываться. Я сейчас пишу разбор файла, в котором мне не обойтись без вектора ( я должен считать узлы геометрии объекта, не зная на этапе прочтения, сколько их. ). По этому я прикладываю усилия по изучению стандартных контейнеров, надеясь добиться такого кода на с++, который не уступал бы использованию указателей по производительности.
Сначала что касается вашего примера с объявлением. Опять-таки, вопрос упирается не в то, что быстрее, а какой компилятор генерирует объектный код. Причем разные компиляторы могут генерировать различный код. Я думаю, выигрыш во времени вы получаете не потому, что один код более эффективен другого, а, скорей всего, потому, что в одном случае компилятор обращается к currentPoint через косвенную адресацию, а во втором случае непосредственно обращается к регистру, так как уже успел засунуть значение этого поля в регистр. Но это на самом деле никак не связано с тем, что один вариант более эффективен другого, а связан с конкретным компилятором и с тем, какой объектный код он генерирует.

Что касается операций сравнения, то на Intel процессорах они обычно выполняются с помощью одной машинной команды: CMP или ее вариации. Например,

C++
1
2
cmp AX,BX
je     address
или

C++
1
2
cmp AX,BX
jl     address
Опять-таки все зависит от того, откуда будут извлекаться операнды. Еси как в моем примере в обоих случаях операнды извлекаются с помощью одних и тех же конструкций, то разницы не будут. Ежели а одном случае операнд извлекается из регистра, а в другом с помощью индексированного тобращения к памяти, то естественно будет разница. Но снова повторю, все это зависит от конкретного компилятора и режима компиляции. Разные компиляторы могут шенерировать разный объектный код. И то, что для одного компилятора может работать быстрее, для другого компилятора может работать медленнее. Ситуация вообще может кардинально измениться, если с одного микропроцессора вы перейдете на другой микропроцессор, так как у них могут быть разные наборы команд.

Что касается вашего знакомого, то это сразу же говорит о том, что он - не профессионал. Его представления об эффективности крайне наивны, так как ему постоянно самому надо писать код по управлению памятью. А это означает, что он может допустить ошибки, и его код не будет столь эффективен, как уже выверенный код для контейнеров. Более того его код может быть вообще не безопасным! Я уж не говорю о сопровождении такого кода другими людьми.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.11.2011, 18:19     Производительность операций #37
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
#include <iostream>
#include <vector>
#include <chrono>
 
int main()
{
   namespace chrono = std::chrono;
 
   const int size = 100000;
   auto now = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
   std::vector<int> vec;
   for (size_t i = 0; i < size; ++i)
   {
      vec.push_back(i);
   }
   std::cout << "Vector time: " << (chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now())
            - now).count() << std::endl;
   int* array = new int[size];
   now = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
   for (size_t i = 0; i < size; ++i)
   {
      array[i] = i;
   }
   std::cout << "Array time: " << (chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now())
         - now).count() << std::endl;
   int* arr = new int[size];
   now = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
   for (size_t i = 0; i < size; ++i)
   {
      *(array + i) = i;
   }
   std::cout << "Pointer time: " << (chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now())
         - now).count() << std::endl;
}
Bash
1
2
3
4
5
forever@pterois:~/My_pro1/cpp_pro$ g++ -o file file.cpp -std=c++0x
forever@pterois:~/My_pro1/cpp_pro$ ./file 
Vector time: 11
Array time: 0
Pointer time: 1
Bash
1
2
3
4
5
forever@pterois:~/My_pro1/cpp_pro$ g++ -o file file.cpp -std=c++0x -O1
forever@pterois:~/My_pro1/cpp_pro$ ./file 
Vector time: 4
Array time: 0
Pointer time: 1
Bash
1
2
3
4
5
forever@pterois:~/My_pro1/cpp_pro$ g++ -o file file.cpp -std=c++0x -O2
forever@pterois:~/My_pro1/cpp_pro$ ./file 
Vector time: 3
Array time: 0
Pointer time: 1
Bash
1
2
3
4
forever@pterois:~/My_pro1/cpp_pro$ ./file 
Vector time: 2
Array time: 1
Pointer time: 0
Bers, Скорость работы с вектором. Не считаю я что получать указатель на первый элемент и работать с ним это правильно.
LosAngeles
Заблокирован
21.11.2011, 18:22     Производительность операций #38
ну первое что бросается в глаза - явно надо сделать обёртки вокруг ассемблерной вставки в виде инлайн функции или макроса, иначе это читать невозможно. Исправить наконец то саму ассемблерную вставку, потому что результат rdtsc помещается в пару edx:eax на ia32, а на intel64 в младшую часть rax и старшую часть rdx, итоговый результат можно получить побитовым или
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
21.11.2011, 18:23  [ТС]     Производительность операций #39
Цитата Сообщение от Сыроежка Посмотреть сообщение
Я уж не говорю о сопровождении такого кода другими людьми.
во-во)) я ему то же самое год назад сказал, он непослушал. Теперь ему двух дипломников дали, заворажённо смотрю, как они будут его код разбирать. Поназаписывал быдлювидюшек по с++, разъясняющих кое-какие детали, дал всем посмотреть, но, боюсь, это не поможет((
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.11.2011, 18:27     Производительность операций
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
21.11.2011, 18:27     Производительность операций #40
Цитата Сообщение от CEBEP Посмотреть сообщение
Не уверен в своих силах для самостоятельной оценки сабжа. Где можно найти информацию о производительности стандартных операций с++ (гуглением не справился, нашел только сравнение реализации на с++, джаве и на нескольких интерпретируемых языках)?
То есть интересует информация плана << : * как 1:15 или <= : == как 25:24... То есть, чрезвычайно интересно знать, какие операции выбирать если есть альтернатива.
Например,
C++
1
x=x+1;
медленнее, чем
C++
1
x++;
C++
1
x++;
медленнее, чем
C++
1
++x;
,
C++
1
x=x+b;
вроде бы медленнее, чем
C++
1
x+=b;
,
C++
1
x=x-1;
медленнее, чем
C++
1
x--;
C++
1
x--;
медленнее, чем
C++
1
--x;
,
C++
1
x=x-b;
вроде бы медленнее, чем
C++
1
x-=b;
C++
1
x=x*b;
медленнее, чем
C++
1
x*=b;
,
C++
1
x*=2;
медленнее, чем
C++
1
x+=x;
, умножение медленнее сложения, но не столько, чтоб выполнять такую замену при любом множителе, кроме двух, но если стоит выбор, два раза умножить и сложить произведения, или сначала сложить, а потом один раз умножить, то лучше один раз умножить, то есть
C++
1
x=a*b+a*d;
медленее, чем
C++
1
x=a*(b+d);
,
C++
1
x=x/b;
медленнее, чем
C++
1
x/=b;
. Сдвиги быстрее, чем деление/умножение на степени двойки.

Добавлено через 2 минуты
Цитата Сообщение от CEBEP Посмотреть сообщение
Разименование указателя в 19.9195 раз быстрее, чем итератора.
Итераторы бывают разные.
Yandex
Объявления
21.11.2011, 18:27     Производительность операций
Ответ Создать тему
Опции темы

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