Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.74/72: Рейтинг темы: голосов - 72, средняя оценка - 4.74
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445

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

20.11.2011, 06:34. Показов 17961. Ответов 135
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не уверен в своих силах для самостоятельной оценки сабжа. Где можно найти информацию о производительности стандартных операций с++ (гуглением не справился, нашел только сравнение реализации на с++, джаве и на нескольких интерпретируемых языках)?
То есть интересует информация плана << : * как 1:15 или <= : == как 25:24... То есть, чрезвычайно интересно знать, какие операции выбирать если есть альтернатива.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.11.2011, 06:34
Ответы с готовыми решениями:

Вставить между цифрами 1, 2,..., 8, 9 в данном порядке, знак одной из 4-х арифметических операций так, чтобы результат восьми послед-х операций =100
Вычисления проводятся слева-направо, ни одна операция не имеет приоритета. Добавлено через 2 минуты задача вынесла моск, прошу помочь

Производительность
Подскажите, где или что почитать о том, как писать БЫСТРЫЕ программы? (про разработку высоконагруженных программ). Копаюсь в интернете -...

Заменить в данной строке знаки арифметических операций названиями противоположных им операций
Заменить в данной строке знаки арифметических операций названиями противоположных им операций.

135
Заблокирован
21.11.2011, 17:29
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от CEBEP Посмотреть сообщение
Но ведь я же продемонстрировал, что в текущем состоянии мой код выдаёт результаты, расходящиеся с тем, что прогнозируете вы (кстати, я доверительно отнёсся к вашему посылу, ведь в первоначальном варианте результаты польностью ему соответствовали). Если расхождение есть, объясните, откуда оно а не говорите что сделает компилятор, если очевидно обратное.
Всегда надо смотреть, какой объектный код генерирует компилятор. И если есть расхождение в генерируемом объектном коде для прединкремента и постинкремента, то определять причину, чем вызвано это расхождение. Как уже неоднократно я писал, если результат постинкремента для фундаментального типа не присваивается другому объекту, то компилятор обычно генерирует такой же код, как и для прединкремента.

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

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

Поэтому я и говорю, что для профессионалов ваш подход и ваши оценки не представяют инетреса. Они интересны лишь из любопытства для новичков, которые узнали, что существует разница между постинкрементом и прединкрементом и ринулиьс это сразу же проверять.
1
385 / 229 / 12
Регистрация: 06.07.2011
Сообщений: 512
21.11.2011, 17:44
Я недавно изучал алгоритм построения гладкой линии, в википедии был приведёт вариант реализации, тщательно избегавший операции умножения. Мне хотелось понять, насколько это оправданно.
да, умножение и деление затратные операции, их желательно избегать по возможности. и то, только в том случае, если ф-ция, где они имеют место быть, вызываются крайне часто и/или критично время работы и/или желательно выполнение на аппаратном уровне. к примеру, примитивные ф-ции компьютерной графики, которые подпадают под все требования.
а вот в инженерном расчете кривых в авиационном деле никто умножения не избегает. так как на фоне общих затрат производительности подобная оптимизация будет столь несущественна, что никак не окупит потраченное на нее время и возможное уменьшение точности расчетов.
1
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 17:47  [ТС]
Цитата Сообщение от Сыроежка Посмотреть сообщение
ринулиьс это сразу же проверять
На самом деле, префиксную и постфиксную форм я сравнивал просто для кучи. я люпблю написать что-нибудь типа
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];, прекрасно понимая все минусы подхода, просто не хочет связываться. Я сейчас пишу разбор файла, в котором мне не обойтись без вектора ( я должен считать узлы геометрии объекта, не зная на этапе прочтения, сколько их. ). По этому я прикладываю усилия по изучению стандартных контейнеров, надеясь добиться такого кода на с++, который не уступал бы использованию указателей по производительности.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 17:47  [ТС]
Цитата Сообщение от Paporotnik Посмотреть сообщение
умножения не избегает
У нас там есть реализация одна, в ней участвуют и умножение и даже одно извлечение корня, но ещё и очень много сложений и обращений к элементам массива массивов (x[i][j]). Вот меня интересовало, стоит ли переписать обращения по индексам в указатели, или это только трата времени, усложнение кода и ничтожный выигрыш. пока однозначно говорить не хочу, но считаю что переписать есть смысл.
0
Заблокирован
21.11.2011, 17:50
Цитата Сообщение от CEBEP Посмотреть сообщение
double k = *++currentPoint == '-' ? .1 : 10;
* * * * ++currentPoint;
За такое по щам получить можно.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 17:54  [ТС]
Я ожидал, что извлечение корня дольше чем умножение раз в 20 как минимум, а оказывается всего в 2,5. Это повод всё-таки переписать алгоритм.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
За такое по щам получить можно.
альтернатива -
C++
1
double k = *++currentPoint++ == '-' ? .1 : 10;
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
21.11.2011, 17:54
CEBEP, Пишите на сях, если смотрите на крохи ускорения и хотите переписать алгоритм с индексной формы в форму указателей. А С++ не трогайте в этом случае.
1
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 18:02  [ТС]
Цитата Сообщение от Paporotnik Посмотреть сообщение
в инженерном расчете кривых в авиационном деле
у нас конечноэлементные и конечнообъёмные расчёты

Короче, по сабжу кто что может сказать? Как повысить объективность теста?
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
21.11.2011, 18:04
Цитата Сообщение от CEBEP Посмотреть сообщение
альтернатива -
А за такое получить нужно
Цитата Сообщение от CEBEP Посмотреть сообщение
У меня на работе есть один умный и хороший специалист (выиграл всероссийскую олимпиаду по сопромату), который принципиально (не потому что лень изучить), не использует стандартные контейнеры а всегда пишет double* array = new double[length];, прекрасно понимая все минусы подхода, просто не хочет связываться
Хороший специалист в сопромате возможно, но не в программировании точно.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 18:07  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
А С++ не трогайте в этом случае.
вот ко мне приходит файл,в котором хранятся переменные. причём стандарт файла такой, что в заголовке колличество переменных не указано. Чем выдумывать что-то для подсчёта переменных (пускай их немного, скажем 600-3000), разумнее воспользоватся вектором. Теперь мне надо решить, что с этим вектором делать, ведь я могу написать double* arr = &dat[0], что куда стрёмнее чем приведённый мною выше код с инкриментами и операцией условия, а могу разобраться с вектором и организовать код так, что переходить на сишные массивы не придётся.

Добавлено через 1 минуту
Цитата Сообщение от fasked Посмотреть сообщение
но не в программировании точно.
Ну вот и я так думаю. Если его мнение так сильно разнится с общепринятым то доверять ему не стоит. По этому и разбираюсь с контейнерами
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
21.11.2011, 18:08
CEBEP, Скорость вектора в любом случае будет ниже, чем использование указателя (если конечно грамотно использовать).
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 18:11  [ТС]
просто ещё на первом курсе написал парсер, он использовал стеки. Когда я перешел от стеков к массивам (просто выделил память под максимально высокий стэк), получил (зависело от контекста) прирост производительности в 80 раз. Ясно же, что если бы проблема решалась только так, то технологии с++ небыли бы настолько популярными. Но полагаться на произвол оптимизатора тоже страшно. Вот и изучаю. Сейчас если доведу написание теста до конца, ещё в IDE Qt запущу тест, разницу посмотрю...
0
Заблокирован
21.11.2011, 18:11
Цитата Сообщение от CEBEP Посмотреть сообщение
В подобном же контексте мне были нитересны < и !=, часто приходится писать for(int i = 0; i != size; ++i), пока мой эксперимент показал, что именно такая запись работает быстрее всего
этого не может быть, оба оператора реализуются одинакова, разница только в переходе, je быстрее jge работает?
0
Заблокирован
21.11.2011, 18:16
Цитата Сообщение от fasked Посмотреть сообщение
double* array = new double[length];
В этой записи кроется угроза. Система, которая пестрит такими записями на самом верхнем уровне - по сути беззащитный ягненок, и может отказать в любой момент


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

Добавлено через 4 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
CEBEP, Скорость вектора в любом случае будет ниже, чем использование указателя (если конечно грамотно использовать).
Что такое скорость вектора? Если имеется ввиду скорость доступа к элементам массива, ничто не мешает получать доступ к элементам посредством обычного указателя точно так же, как и при работе с обычными дин. массивами.
А если слегка подшаманить, можно подружить вектор с массивами на стеке. Для особо капризных случаев. Только вот.. в 99% случаев этого нафег не нужно.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 18:16  [ТС]
Цитата Сообщение от LosAngeles Посмотреть сообщение
je быстрее jge работает?
ну я тоже с кое-чем в тесте не согласен, это говорит что он или запущен или скомпилирован неверно. Если бы мы не отвлекались, а разбирались что исправить в проекте, возможно к 4 странице топа уже бы имели классный текст, с логически понятными результатами, сходящимися с теорией...
0
Заблокирован
21.11.2011, 18:17
Цитата Сообщение от 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
Опять-таки все зависит от того, откуда будут извлекаться операнды. Еси как в моем примере в обоих случаях операнды извлекаются с помощью одних и тех же конструкций, то разницы не будут. Ежели а одном случае операнд извлекается из регистра, а в другом с помощью индексированного тобращения к памяти, то естественно будет разница. Но снова повторю, все это зависит от конкретного компилятора и режима компиляции. Разные компиляторы могут шенерировать разный объектный код. И то, что для одного компилятора может работать быстрее, для другого компилятора может работать медленнее. Ситуация вообще может кардинально измениться, если с одного микропроцессора вы перейдете на другой микропроцессор, так как у них могут быть разные наборы команд.

Что касается вашего знакомого, то это сразу же говорит о том, что он - не профессионал. Его представления об эффективности крайне наивны, так как ему постоянно самому надо писать код по управлению памятью. А это означает, что он может допустить ошибки, и его код не будет столь эффективен, как уже выверенный код для контейнеров. Более того его код может быть вообще не безопасным! Я уж не говорю о сопровождении такого кода другими людьми.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
21.11.2011, 18:19
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, Скорость работы с вектором. Не считаю я что получать указатель на первый элемент и работать с ним это правильно.
1
Заблокирован
21.11.2011, 18:22
ну первое что бросается в глаза - явно надо сделать обёртки вокруг ассемблерной вставки в виде инлайн функции или макроса, иначе это читать невозможно. Исправить наконец то саму ассемблерную вставку, потому что результат rdtsc помещается в пару edx:eax на ia32, а на intel64 в младшую часть rax и старшую часть rdx, итоговый результат можно получить побитовым или
1
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
21.11.2011, 18:23  [ТС]
Цитата Сообщение от Сыроежка Посмотреть сообщение
Я уж не говорю о сопровождении такого кода другими людьми.
во-во)) я ему то же самое год назад сказал, он непослушал. Теперь ему двух дипломников дали, заворажённо смотрю, как они будут его код разбирать. Поназаписывал быдлювидюшек по с++, разъясняющих кое-какие детали, дал всем посмотреть, но, боюсь, это не поможет((
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
21.11.2011, 18:27
Цитата Сообщение от 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 раз быстрее, чем итератора.
Итераторы бывают разные.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.11.2011, 18:27

Доказать равенства, используя свойства операций над множествами и определения операций
Доказать равенства, используя свойства операций над множествами и определения операций. Дальше как не пробовал, не могу привести к...

Доказать равенства, используя свойства операций над множествами и определения операций
Доказать равенства, используя свойства операций над множествами и определения операций. A\subseteq C, B\subseteq D \Rightarrow A\times...

Сколько нужно провести операций, чтобы 13 операций подряд были успешными?
Вероятность успешной операции = 63% Сколько нужно провести операций, чтобы 13 операций подряд были успешными???

Доказать равенства, используя свойства операций над множествами и определения операций
Доказать равенства, используя свойства операций над множествами и определения операций. б) Ax(B\C)=(AxB)\(AxC). Почему график не...

Напечатать все знаки арифметических операций и операций отношения
Напечатать все знаки арифметических операций и операций отношения,которые входят в заданый массив и все знаки арифметических операций и...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
сукцессия 30. Фосфорный и азотный замки по "честному" закону лимитирования Либиха
anaschu 16.07.2026
Основные достижения за последние дни 1. Механизм отложенного высвобождения фосфора Добавлен специальный пул для медленного разложения меланизированных гиф ЕСМ Реализована разная скорость. . .
Запрет пометки на удаление и отмены проведения
Maks 16.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "ПутевойЛист" разработанного в КА2. Задача: запретить помечать на удаление и отменять проведения путевого листа при условии, если он сдан. . .
Как надо было делать правильно - вообще не слушать ИИ, его дело - текст.
Hrethgir 15.07.2026
А вообще надо было делать не так, чтобы не исправлять ошибку https:/ / www. cyberforum. ru/ blogs/ 223907/ 10996. html , правильно было : удалил кнопку, а потом добавил её. Всё это стресс конечно. Почему?. . .
Знаете, от чего появляется стресс?
kumehtar 15.07.2026
Стресс появляется оттого, что вы, зная как поступить правильно, делаете наоборот. Ларри Уингет
Нас бьют, а мы крепчаем? Какая чушь!
kumehtar 15.07.2026
Вот это вот бытующее мнение, что человек меняется только под действием проблем, всегда считал вредоносным. Поверь, от проблем у людей появляются не изменения, а нервное расстройство и ПТСР. А. . .
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru