Здравствуйте, getch, Вы писали:
К>>Попробуй сравнить дизасмы программ со строчкой и без неё. Скорее всего, у оптимизатора крыша поехала.
G>Приложил Asm. К сожалению, не знаю ассемблера. Странно только, что длина Asm варианта с выводом на консоль (который в 2 раза медленней) меньше, чем без вывода.
Ха, так очевидно же.
Если в main есть вывод, то он не стал инлайнить Print.
Вместо этого он
— вынужден честно вычислять CalcBars
— делает вызов
— не может выполнить оптимизации, связанные с выполнением тела Print в цикле
G>По наивности своей идеализировал возможности столь популярного оптимизатора компилятора VSC++. Теперь понимаю, что оптимизатор далеко не идеал.
А вот незачем /Oy делать. Это довольно глючный режим, а в старых версиях там вообще баги встречались.
Попробуй /Ox.
Перекуём баги на фичи!
Re: Замена типа переменной long int на long long без вычислений замедляет код на
К>казалось бы, если уж тупить, то в загрузке в регистр, а не в проверке и записи — но профайлеры тычут пальцем в test, там почти на два порядка !!! больше времени тратится, чем в предшествующей и последующей инструкциях.
ИМХО, это кэш. test тормозит, дожидаясь загрузки edx.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[12]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, Кодт, Вы писали: К>Ха, так очевидно же. К>Если в main есть вывод, то он не стал инлайнить Print. К>Вместо этого он К>- вынужден честно вычислять CalcBars К>- делает вызов К>- не может выполнить оптимизации, связанные с выполнением тела Print в цикле
Если закомментировать строчку:
CalcBars += CurrentBar;
Двухкратное замедление остается. Непонятно, что мешает компилятору заинлайнить Print в цикле. Все смахивает больше просто на баг компилятора.
К>А вот незачем /Oy делать. Это довольно глючный режим, а в старых версиях там вообще баги встречались. К>Попробуй /Ox.
Манипуляции с /Oy (опустить указатели на фреймы) не помогают убрать двухкратное замедление, при этом /Ox прописан. Однако, на моих задачах включение этой (/Oy) опции дает +5% к скорости.
Re[5]: Замена типа переменной long int на long long без вычислений замедляет код
G>Все как раз очень практично. Дело в том, что мне нужно оптимизировать именно однопоточный вариант, т.к. далее планирую ускорить расчеты в ~1000 раз через запуск в облаке (режим мат. моделирования). Там C-подобный однопоточный язык, но для облака в целях безопасности не разрешается использование DLL. Зато есть встроенная поддержка OpenCL, которую потом добавлю, когда разберусь с ней.
Может, кто посоветует другое облачное решение, где все также автоматизировано (ничего придумывать для распараллеливания почти не нужно), но есть возможность запускать компилируемый код от стандартных языков программирования?
Re[13]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, getch, Вы писали:
G>Если закомментировать строчку: G>
CalcBars += CurrentBar;
G>Двухкратное замедление остается.
Потому что не эта строчка влияет на встраивание, а та, где cout.
G> Непонятно, что мешает компилятору заинлайнить Print в цикле. Все смахивает больше просто на баг компилятора.
Где здесь баг? Оптимизатор имеет право поступать на своё усмотрение, сохраняя логику работы программы. К логике претензии есть?
Если хочешь, попробуй объявить __forceinline Print, может быть, это поможет.
К>>А вот незачем /Oy делать. Это довольно глючный режим, а в старых версиях там вообще баги встречались. К>>Попробуй /Ox. G>Манипуляции с /Oy (опустить указатели на фреймы) не помогают убрать двухкратное замедление, при этом /Ox прописан. Однако, на моих задачах включение этой (/Oy) опции дает +5% к скорости.
/Ox и /Oy, по-моему, взаимоисключающие опции. Компилятор должен сделать выбор между "быстрее" и "короче", и что он выберет —
Но вопрос сейчас не об этом. А о том, как писать код, дружественный к оптимизатору.
Я вот не думаю, что интенсивная работа со статическими переменными — это дружественный код.
Если бы я был компилятором, то встретив в теле Print любую внешнюю функцию — будь то подгружаемая из внешней dll GetTickCount или сводящаяся к ряду косвенностей и виртуальных вызовов cout<<anything, — должен был бы записать текущие значения статиков из регистров в память, а по возвращении из внешней функции — всосать их в регистры обратно. Потому что, а вдруг там рекурсия?
Перекуём баги на фичи!
Re[14]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, Кодт, Вы писали:
К>Но вопрос сейчас не об этом. А о том, как писать код, дружественный к оптимизатору. К>Я вот не думаю, что интенсивная работа со статическими переменными — это дружественный код. К>Если бы я был компилятором, то встретив в теле Print любую внешнюю функцию — будь то подгружаемая из внешней dll GetTickCount или сводящаяся к ряду косвенностей и виртуальных вызовов cout<<anything, — должен был бы записать текущие значения статиков из регистров в память, а по возвращении из внешней функции — всосать их в регистры обратно. Потому что, а вдруг там рекурсия?
Ну а как без статиков тогда обойтись? Запихивать все на глобальный уровень — архитектурно-эстетически противно, да и также при каждом вызове функции надо будет их в регисры пропихивать.
Re[6]: Замена типа переменной long int на long long без вычислений замедляет код
Здравствуйте, Kubyshev Andrey, Вы писали:
KA>Никакого замедления нет, ключи самые обычные, я ничего не менял. KA>/O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /Gy /Yu"stdafx.h" /Fp"Release\testrsdn.pch" /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /errorReport:prompt
KA>Пацаны, хорошь гадать на пустом месте, ниче не замедляется.
Т.е. скорость выполнения кода c/без обозначенной выше строчки не меняется? Только что запустил с вашими ключами, разница в два раза. У меня на разных машинах ситуация повторяется.
Re[8]: Замена типа переменной long int на long long без вычислений замедляет код
Все у вас работает так как и должно. Магии здесь никакой нет. Замедление на 15% происходит, когда складываются 64 битные значения вместо 32 битных в цикле. Замедление в 2 раза происходит, когда inlining для Print отрубается после добавления cout перед циклом. В этом случае добавляется инструкция call в тело цикла. Проблема у вас в том, что цикл повторяется огромное число раз. Небольшое изменение в теле цикла сильно влияет на результат. Интересно, что это за задача такая в которой 100 млрд. итераций?
Re[15]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, getch, Вы писали:
G>Ну а как без статиков тогда обойтись? Запихивать все на глобальный уровень — архитектурно-эстетически противно, да и также при каждом вызове функции надо будет их в регисры пропихивать.
Я без понятия, как обойтись без статиков в реальном коде, который я не видел.
А здесь можно выполнить ряд преобразований кода, который сведётся к тому, чтобы проинлайнить Print вручную, раз уж компилятор не захотел делать это сам.
И смысл? Ну, мы увидим, что 64-битная арифметика на 5 или 15% тормознутее 32-битной, и сделаем очевидный вывод: не использовать 64 бита без нужды.
Если нужна помощь в рефакторинге реального кода, так это... код в студию. Что-нибудь придумаем.
Перекуём баги на фичи!
Re[9]: Замена типа переменной long int на long long без вычислений замедляет код
Здравствуйте, cserg, Вы писали:
C>Все у вас работает так как и должно. Магии здесь никакой нет. Замедление на 15% происходит, когда складываются 64 битные значения вместо 32 битных в цикле. Замедление в 2 раза происходит, когда inlining для Print отрубается после добавления cout перед циклом. В этом случае добавляется инструкция call в тело цикла. Проблема у вас в том, что цикл повторяется огромное число раз. Небольшое изменение в теле цикла сильно влияет на результат. Интересно, что это за задача такая в которой 100 млрд. итераций?
Странно просто, что компилятор делает call в цикле за вместо inlining Print. Как на это решение влияет cout перед циклом — не ясно. Но факт — влияет все же. Хотя ничто ему не мешает сделать все правильно.
100 млрд — это с потолка взятое число для примера. Но вообще подобное количество вычислений — далеко не редкость. Занимаюсь просто исследованием временных рядов. А там без огромных вычислений довольно туго, поэтому и облако и GPU в планах подключить. Многосуточные расчеты — обычное дело. Ну как и при мат. моделировании и расчетах физических свойств огромных по размерам сеток. Вообщем, задач загрузить под завязку даже суперкомрьютеры полно. Лишь бы не в лоб и со знанием дела.
Re[16]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, getch, Вы писали:
G>Странно просто, что компилятор делает call в цикле за вместо inlining Print. Как на это решение влияет cout перед циклом — не ясно. Но факт — влияет все же. Хотя ничто ему не мешает сделать все правильно.
Может, ему сам факт cout<< не нравится.
Может, критическое значение имеет размер функции main: если она меньше порога по длине, или нагрузке на стек, или нагрузке на регистры, то инлайнит содержимое, а если больше порога — то заведомо не инлайнит.
Попробуй засунуть этот cout<< внутрь Print и посмотреть, проинлайнится он или нет.
Перекуём баги на фичи!
Re[11]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, Кодт, Вы писали:
К>Может, ему сам факт cout<< не нравится. К>Может, критическое значение имеет размер функции main: если она меньше порога по длине, или нагрузке на стек, или нагрузке на регистры, то инлайнит содержимое, а если больше порога — то заведомо не инлайнит. К>Попробуй засунуть этот cout<< внутрь Print и посмотреть, проинлайнится он или нет.
Если поместить cout в Print (только ни к чему), то замедления не происходит. Вообщем, данное замедление — это просто баг, оправдание которому быть не может. Надеюсь, исправят.
Re[12]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, getch, Вы писали:
G>Если поместить cout в Print (только ни к чему), то замедления не происходит. Вообщем, данное замедление — это просто баг, оправдание которому быть не может. Надеюсь, исправят.
Это не баг, а "хочу фичу! хочухочухочу!"
Никто не обещает инлайнить функцию во что бы то ни стало. Даже __forceinline не даёт 100% гарантии.
Чёрт знает, по какой эвристике компилятор решил, что без cout инлайн возможен, а с ним — нет.
Кстати!!!! Баг у тебя, а не у компилятора.
Ты почему не написал inline void Print ??
Всё, тема закрыта.
Перекуём баги на фичи!
Re[13]: Замена типа переменной long int на long long без вычислений замедляет ко
Здравствуйте, Кодт, Вы писали:
К>Кстати!!!! Баг у тебя, а не у компилятора. К>Ты почему не написал inline void Print ??
Потому что компилятор настроен так, чтобы инлайнить все, что только может. Дописал все же inline — замедление никуда не делось.
К>Всё, тема закрыта.
Согласен. Пусть тема остается, как простой пример явного бага оптимизатора компилятора.
Re[14]: Замена типа переменной long int на long long без вычислений замедляет ко