KA>Давай уже генери asm код и показывай что там такое! Сгенерил код для исходника в первом посте. Ассемблера не знаю, поэтому приложил варианты сразу от нескольких ключей (/FA, /FAs, /FAcs).
Отличий совсем немного:
Re[2]: Замена типа переменной long int на long long без вычислений замедляет код
Подозреваю, что дело в оптимизаторе.
Если нет места, где счётчик используется, то этот счётчик можно просто выкинуть.
Если место есть (и компилятор не смог догадаться, что условие всегда ложно; либо догадался, но далеко идущих выводов не сделал), — то не выкидывает и молотит 32- или 64-битную арифметику соответственно.
Перекуём баги на фичи!
Re[3]: Замена типа переменной long int на long long без вычислений замедляет код
К>Если нет места, где счётчик используется, то этот счётчик можно просто выкинуть.
Поясните дилетанту, что имеется в виду под счетчиком? Как помочь компилятору не тупить?
К сожалению, походу обсуждения родилась непонятная проблема, которая актуальна и для int и для long: G>Т.е. у меня замедление, а у вас наоборот — ускорение.
G>Но самое странное, когда (чтобы не перепутать случаи) добавил эти строчки:
G>
int main(int argc, char* argv[])
G>{
G>// unsigned long int CalcBars = 0, CurrentBar = 100;
G>// Замена на эту строчку замедляет выполнение программы на ~ 15%.
G> unsigned long long CalcBars = 0, CurrentBar = 100;
G> std::cout << "SizeOf(Type) = " << sizeof(unsigned long long) << " bytes." << std::endl; // добавил
G> std::cout << "SizeOf(CalcBars) = " << sizeof(&CalcBars) << " bytes." << std::endl; // добавил
G>
G> for (long long i = 0; i < AMOUNT; i++)
G> .....
G>
Здравствуйте, getch, Вы писали:
К>>Если нет места, где счётчик используется, то этот счётчик можно просто выкинуть. G>Поясните дилетанту, что имеется в виду под счетчиком? Как помочь компилятору не тупить?
А, не, это не счётчик. Но всё равно.
Если CalcBars используется, то он передаётся в функцию, и это стоит определённых денег.
Если не используется, то не передаётся.
G>К сожалению, походу обсуждения родилась непонятная проблема, которая актуальна и для int и для long: G>>Т.е. у меня замедление, а у вас наоборот — ускорение.
G>>Но самое странное, когда (чтобы не перепутать случаи) добавил эти строчки:
G>>[ccode] G>> std::cout << "SizeOf(Type) = " << sizeof(unsigned long long) << " bytes." << std::endl; // добавил G>> std::cout << "SizeOf(CalcBars) = " << sizeof(&CalcBars) << " bytes." << std::endl; // добавил G>>
Ничего странного нет.
Во-первых, sizeof(указатель-на-CalcBars) = sizeof(void*) = 4 байта на x86.
Во-вторых, пока ты не брал адрес, компилятор имел право держать эту переменную "в уме", в каком-то из 64-битных регистров. А с адресом, ты приземлил переменную в локальное хранилище, на стек. Вот тебе, бабушка, и двукратные тормоза.
Перекуём баги на фичи!
Re[5]: Замена типа переменной long int на long long без вычислений замедляет код
Здравствуйте, Кодт, Вы писали:
К>Если CalcBars используется, то он передаётся в функцию, и это стоит определённых денег. К>Если не используется, то не передаётся.
При включённой оптимизации, разумеется.
На ассемблерном листинге видно, что функция Print была проинлайнена внутрь main.
Ну а дальше компилятор сам решает, какие локальные переменные используются, а какие можно было бы и выкинуть.
Перекуём баги на фичи!
Re[5]: Замена типа переменной long int на long long без вычислений замедляет код
К>Во-вторых, пока ты не брал адрес, компилятор имел право держать эту переменную "в уме", в каком-то из 64-битных регистров. А с адресом, ты приземлил переменную в локальное хранилище, на стек. Вот тебе, бабушка, и двукратные тормоза.
Двухкратное просидание производительности никуда не девается.
Понимаю, что можно теоретизировать и высказывать различные гипотезы. Но многие из них разбиваются о реальность, если все же запустить пример у себя. Попробуйте просто.
Почему тормоза таки происходят? Если нет объяснения, то, может, есть рецепт, как избежать этих проблем?
Re[6]: Замена типа переменной long int на long long без вычислений замедляет код
К>На ассемблерном листинге видно, что функция Print была проинлайнена внутрь main. К>Ну а дальше компилятор сам решает, какие локальные переменные используются, а какие можно было бы и выкинуть.
Непонятно, почему от типа переменной зависит решение компилятора, используется ли она или нет?
Тут очень многие, наверное, используют VS 2012. Как правильно делать-то, чтобы идиотские тормоза не всплывали?
Re[7]: Замена типа переменной long int на long long без вычислений замедляет код
Здравствуйте, getch, Вы писали:
G>Непонятно, почему от типа переменной зависит решение компилятора, используется ли она или нет?
Используется она или нет, зависит от наличия sizeof(&CalcBars) и if(does-not-matter) cout << CalcBars.
Если есть адрес — будет переменная на стеке. Это дороже всего.
Если нет адреса — будет в регистре. Это дешевле.
Если не используется — то вообще прекрасно.
Чем дороже, тем ярче разница между long long и long.
G>Тут очень многие, наверное, используют VS 2012. Как правильно делать-то, чтобы идиотские тормоза не всплывали?
Так уже сказал watchmaker — профилировать не что попало надуманное, а реальный код.
Или сломать оптимизацию. Может быть, __declspec (noinline) Print будет достаточно.
Перекуём баги на фичи!
Re[8]: Замена типа переменной long int на long long без вычислений замедляет код
К>Так уже сказал watchmaker — профилировать не что попало надуманное, а реальный код. К>Или сломать оптимизацию. Может быть, __declspec (noinline) Print будет достаточно.
Говорил уже, как в нагруженном коде получил тормоза. Потом методом исключения создал этот пример. Если этот пример начинаю загружать различными вычислениями, от этого разницы в тормозах никуда не уходит.
На очень сильно загруженной вычислениями задаче происходит падение на 5%. При этом замена int на long делается для переменной, которая практически ну никак не участвует в расчетах.
И прошу заметить, что средняя скорость на любом интервале падает одинаково — 5%. Т.е. эффект такой же, как будто на 5% понизил частоту процессора.
А замедление в два раза после добавления безобидной строчки cout перед циклом (без обращения к CalcBars) — это вообще безобразие.
Никого не хочу задеть, но, судя по ответам, складывается впечатление, что никого особо не заботит падение производительности своих программ. Работает — и хорошо.
Все же хотел бы разобраться, не закрывая глаза на явные странности.
Re: Замена типа переменной long int на long long без вычислений замедляет код на
Здравствуйте, getch, Вы писали:
G>А замедление в два раза после добавления безобидной строчки cout перед циклом (без обращения к CalcBars) — это вообще безобразие.
Это ввод-вывод-то безобидный, да еще с endl, который сбрасывает буфферы?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: Замена типа переменной long int на long long без вычислений замедляет код
Ops>Это ввод-вывод-то безобидный, да еще с endl, который сбрасывает буфферы?
Да, совершенно безобидный, т.к. вызывается всего один раз и перед циклом for:
// std::cout << "SizeOf(Type) = " << sizeof(unsigned long long) << " bytes." << std::endl; // раскомментировав эту строчу, получите замедление в два раза.
// std::cout << std::endl; // А ВОТ ТАК НЕ ЗАМЕДЛЯЕТ!for (long long i = 0; i < AMOUNT; i++)
Либо же я что-то глубоко не понимаю, раз считаю странным замедление скорости выполнения всей программы в два раза лишь от того, что в начале программы что-то вывели на консоль.
Чтобы мне не быть голословным, убедитесь в этом у себя, запустив.
Re[3]: Замена типа переменной long int на long long без вычислений замедляет код
KA>Я скачал и запустил, KA>Мне кажется у тебя неправильные измерительные приборы. KA>Вот мой вывод, колебания просто огромны, по ним ничего нельзя замерить.
Измерительные приборы как раз правильные — скорость исполнения на любом этапе выполнения программы одинаковая. Расчетное время окончания вычислений в самом начале выполнения программы полностью совпадает с фактическим. Колебания практически отсутствуют. Возможно, вас ввел в заблуждение сильные изменения показателя "Average Velocity" в режиме unsigned long int. Это простое переполнение типа (100 млрд не вписываются). В режиме unsigned long long переполнения нет — показатель "Average Velocity" стабильный.
В программе нет детских ошибок. Все перепроверил перед тем, как постить. Посмотирите внимательно код — он очень простой.
unsigned long int:
Finished 1%, Time = 1 / 191
Average Velocity = 628620 thousands bars/se
......
Finished 99%, Time = 190 / 1 - расчетное время (191 сек.) совпадает с фактическим.
Average Velocity = 525 thousands bars/sec. - результат переполнения unsigned long int
unsigned long long:
Finished 1%, Time = 2 / 220
Average Velocity = 44843049 thousands bars/sec.
......
[b]Finished 99%, Time = 218 / 2[b] - расчетное время (220 сек.) совпадает с фактическим.
Average Velocity = 45303533 thousands bars/sec. - показатель стабилен: нет переполнения unsigned long long
Re[4]: Замена типа переменной long int на long long без вычислений замедляет код
странно все это... вы говорите, что производительность критична, но при этом, вы реализовали задачу на уровне первого класса %)
если вы таки не лжете, и производительность таки критична, скажите, почему реализация в один поток? или, что лучше, почему не используется OMP? или, что гораздо лучше — OMP+SIMD.
или ваша задача не имеет практического применения? это просто исследовательская работа на тему "почему 64ех битные операции на 32ух битном хосте выполняются медленнее?"
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[9]: Замена типа переменной long int на long long без вычислений замедляет код
Здравствуйте, getch, Вы писали:
G>На очень сильно загруженной вычислениями задаче происходит падение на 5%. При этом замена int на long делается для переменной, которая практически ну никак не участвует в расчетах.
Ну как же она не используется, если в цикле делается её инкремент на каждой итерации.
Дальше всё упирается в оптимизирующий компилятор: сможет он её выбросить за ненадобностью, приземлить в регистр или приземлить на стек.
G>А замедление в два раза после добавления безобидной строчки cout перед циклом (без обращения к CalcBars) — это вообще безобразие.
Вот это действительно странно.
Попробуй сравнить дизасмы программ со строчкой и без неё. Скорее всего, у оптимизатора крыша поехала.
G>Никого не хочу задеть, но, судя по ответам, складывается впечатление, что никого особо не заботит падение производительности своих программ. Работает — и хорошо.
Ешё как заботит. За один процент бьёмся.
Я вот, например, тремя профайлерами воспользовался, чтобы найти узкие места. Несколько мест изничтожил, одно само внезапно испарилось, зато пара мест не поддаётся пониманию.
Например, код
bool isZero = some->var == 0;
три инструкции (воспроизвожу по памяти)
mov edx, dword ptr [some+var]
test edx, edx
setz cl
казалось бы, если уж тупить, то в загрузке в регистр, а не в проверке и записи — но профайлеры тычут пальцем в test, там почти на два порядка !!! больше времени тратится, чем в предшествующей и последующей инструкциях.
Перекуём баги на фичи!
Re[5]: Замена типа переменной long int на long long без вычислений замедляет код
X>странно все это... вы говорите, что производительность критична, но при этом, вы реализовали задачу на уровне первого класса %) X>если вы таки не лжете, и производительность таки критична, скажите, почему реализация в один поток? или, что лучше, почему не используется OMP? или, что гораздо лучше — OMP+SIMD. X>или ваша задача не имеет практического применения? это просто исследовательская работа на тему "почему 64ех битные операции на 32ух битном хосте выполняются медленнее?"почему 64ех битные операции на 32ух битном хосте выполняются медленнее?
Все как раз очень практично. Дело в том, что мне нужно оптимизировать именно однопоточный вариант, т.к. далее планирую ускорить расчеты в ~1000 раз через запуск в облаке (режим мат. моделирования). Там C-подобный однопоточный язык, но для облака в целях безопасности не разрешается использование DLL. Зато есть встроенная поддержка OpenCL, которую потом добавлю, когда разберусь с ней.
Поэтому такой десткий сад на первый взгляд. К тому же я дилетант в программировании.
Re[10]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, getch, Вы писали:
G>>На очень сильно загруженной вычислениями задаче происходит падение на 5%. При этом замена int на long делается для переменной, которая практически ну никак не участвует в расчетах. К>Ну как же она не используется, если в цикле делается её инкремент на каждой итерации. К>Дальше всё упирается в оптимизирующий компилятор: сможет он её выбросить за ненадобностью, приземлить в регистр или приземлить на стек.
Да, в этом разобрались, спасибо.
G>>А замедление в два раза после добавления безобидной строчки cout перед циклом (без обращения к CalcBars) — это вообще безобразие. К>Вот это действительно странно. К>Попробуй сравнить дизасмы программ со строчкой и без неё. Скорее всего, у оптимизатора крыша поехала.
Приложил Asm. К сожалению, не знаю ассемблера. Странно только, что длина Asm варианта с выводом на консоль (который в 2 раза медленней) меньше, чем без вывода.
G>>Никого не хочу задеть, но, судя по ответам, складывается впечатление, что никого особо не заботит падение производительности своих программ. Работает — и хорошо. К>Ешё как заботит. За один процент бьёмся. К>Я вот, например, тремя профайлерами воспользовался, чтобы найти узкие места. Несколько мест изничтожил, одно само внезапно испарилось, зато пара мест не поддаётся пониманию.
По наивности своей идеализировал возможности столь популярного оптимизатора компилятора VSC++. Теперь понимаю, что оптимизатор далеко не идеал.