Re[11]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Кодт Россия  
Дата: 01.09.13 10:38
Оценка:
Здравствуйте, getch, Вы писали:

К>>Попробуй сравнить дизасмы программ со строчкой и без неё. Скорее всего, у оптимизатора крыша поехала.


G>Приложил Asm. К сожалению, не знаю ассемблера. Странно только, что длина Asm варианта с выводом на консоль (который в 2 раза медленней) меньше, чем без вывода.


Ха, так очевидно же.
Если в main есть вывод, то он не стал инлайнить Print.
Вместо этого он
— вынужден честно вычислять CalcBars
— делает вызов
— не может выполнить оптимизации, связанные с выполнением тела Print в цикле

G>По наивности своей идеализировал возможности столь популярного оптимизатора компилятора VSC++. Теперь понимаю, что оптимизатор далеко не идеал.


А вот незачем /Oy делать. Это довольно глючный режим, а в старых версиях там вообще баги встречались.
Попробуй /Ox.
Перекуём баги на фичи!
Re: Замена типа переменной long int на long long без вычислений замедляет код на
От: jazzer Россия Skype: enerjazzer
Дата: 01.09.13 11:14
Оценка: :)
Здравствуйте, getch, Вы писали:

G>2. Каковы реальные причины этого?


Явно релятивистский эффект
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Замена типа переменной long int на long long без вычислений замедляет код
От: Kubyshev Andrey  
Дата: 01.09.13 11:14
Оценка:
Попробовал с long long. В упор не вижу проблемы.

Вот 64 бита,

U:\Users\user\Documents\Visual Studio 2008\Projects\testrsdn\x64\Release>testrsdn.exe

SizeOf(Type) = 8 bytes.
Finished 1%, Time = 2 / 200
Average Velocity = 49309664 thousands bars/sec.
Finished 2%, Time = 4 / 199
Average Velocity = 49115913 thousands bars/sec.
Finished 3%, Time = 6 / 198
Average Velocity = 48804294 thousands bars/sec.
Finished 4%, Time = 8 / 196

Вот 32 бита.

U:\Users\user\Documents\Visual Studio 2008\Projects\testrsdn\Release>testrsdn.exe

SizeOf(Type) = 8 bytes.
Finished 1%, Time = 3 / 302
Average Velocity = 32701111 thousands bars/sec.
Finished 2%, Time = 6 / 299
Average Velocity = 32701111 thousands bars/sec.
Finished 3%, Time = 9 / 297
Average Velocity = 32647731 thousands bars/sec.
Finished 4%, Time = 12 / 293
Average Velocity = 32703785 thousands bars/sec.
Re[10]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Ops Россия  
Дата: 01.09.13 11:35
Оценка: 1 (1)
Здравствуйте, Кодт, Вы писали:

К>Например, код

К>
К>bool isZero = some->var == 0;
К>

К>три инструкции (воспроизвожу по памяти)
К>
К>mov edx, dword ptr [some+var]
К>test edx, edx
К>setz cl
К>

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

ИМХО, это кэш. test тормозит, дожидаясь загрузки edx.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[12]: Замена типа переменной long int на long long без вычислений замедляет ко
От: getch  
Дата: 01.09.13 12:33
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Ха, так очевидно же.
К>Если в main есть вывод, то он не стал инлайнить Print.
К>Вместо этого он
К>- вынужден честно вычислять CalcBars
К>- делает вызов
К>- не может выполнить оптимизации, связанные с выполнением тела Print в цикле

Если закомментировать строчку:
CalcBars += CurrentBar;


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

К>А вот незачем /Oy делать. Это довольно глючный режим, а в старых версиях там вообще баги встречались.

К>Попробуй /Ox.

Манипуляции с /Oy (опустить указатели на фреймы) не помогают убрать двухкратное замедление, при этом /Ox прописан. Однако, на моих задачах включение этой (/Oy) опции дает +5% к скорости.
Re[5]: Замена типа переменной long int на long long без вычислений замедляет код
От: getch  
Дата: 01.09.13 12:53
Оценка:
Здравствуйте, Kubyshev Andrey, Вы писали:

KA>Попробовал с long long. В упор не вижу проблемы.


KA>Вот 64 бита,


KA>U:\Users\user\Documents\Visual Studio 2008\Projects\testrsdn\x64\Release>testrsdn.exe


KA>SizeOf(Type) = 8 bytes.

KA>Finished 1%, Time = 2 / 200
KA>Average Velocity = 49309664 thousands bars/sec.
KA>Finished 2%, Time = 4 / 199
KA>Average Velocity = 49115913 thousands bars/sec.
KA>Finished 3%, Time = 6 / 198
KA>Average Velocity = 48804294 thousands bars/sec.
KA>Finished 4%, Time = 8 / 196

KA>Вот 32 бита.


KA>U:\Users\user\Documents\Visual Studio 2008\Projects\testrsdn\Release>testrsdn.exe


KA>SizeOf(Type) = 8 bytes.

KA>Finished 1%, Time = 3 / 302
KA>Average Velocity = 32701111 thousands bars/sec.
KA>Finished 2%, Time = 6 / 299
KA>Average Velocity = 32701111 thousands bars/sec.
KA>Finished 3%, Time = 9 / 297
KA>Average Velocity = 32647731 thousands bars/sec.
KA>Finished 4%, Time = 12 / 293
KA>Average Velocity = 32703785 thousands bars/sec.

Какие ключи у вас стоят?

У меня для long long на x64 раскомментирование строчки:
std::cout << "SizeOf(CalcBars) = " << std::endl;


дает замедление на 60%. На Win32 — в два раза.

Результаты long long без этой строчки такие:
x64:
D:\Ivan\Documents\Projects\Test\x64\Release\Test.exe

Finished 1%, Time = 2 / 205
Average Velocity = 48216007 thousands bars/sec.

win32:
D:\Ivan\Documents\Projects\Test\Release\Test.exe

Finished 1%, Time = 2 / 216
Average Velocity = 45787545 thousands bars/sec.


Соответственно, для long int:
x64:
D:\Ivan\Documents\Projects\Test\x64\Release\Test.exe

Finished 1%, Time = 2 / 208
Average Velocity = 577280 thousands bars/sec.

win32:
D:\Ivan\Documents\Projects\Test\Release\Test.exe

Finished 1%, Time = 2 / 233
Average Velocity = 516242 thousands bars/sec.


Как уже выше показали после анализа asm, работа с long long дороже. Разовое замедление, к сожалению, на баг компилятора похоже.
Re[6]: Замена типа переменной long int на long long без вычислений замедляет код
От: getch  
Дата: 01.09.13 13:15
Оценка:
G>Все как раз очень практично. Дело в том, что мне нужно оптимизировать именно однопоточный вариант, т.к. далее планирую ускорить расчеты в ~1000 раз через запуск в облаке (режим мат. моделирования). Там C-подобный однопоточный язык, но для облака в целях безопасности не разрешается использование DLL. Зато есть встроенная поддержка OpenCL, которую потом добавлю, когда разберусь с ней.

Может, кто посоветует другое облачное решение, где все также автоматизировано (ничего придумывать для распараллеливания почти не нужно), но есть возможность запускать компилируемый код от стандартных языков программирования?
Re[13]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Кодт Россия  
Дата: 01.09.13 14:29
Оценка:
Здравствуйте, 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 без вычислений замедляет ко
От: getch  
Дата: 01.09.13 14:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Но вопрос сейчас не об этом. А о том, как писать код, дружественный к оптимизатору.

К>Я вот не думаю, что интенсивная работа со статическими переменными — это дружественный код.
К>Если бы я был компилятором, то встретив в теле Print любую внешнюю функцию — будь то подгружаемая из внешней dll GetTickCount или сводящаяся к ряду косвенностей и виртуальных вызовов cout<<anything, — должен был бы записать текущие значения статиков из регистров в память, а по возвращении из внешней функции — всосать их в регистры обратно. Потому что, а вдруг там рекурсия?

Ну а как без статиков тогда обойтись? Запихивать все на глобальный уровень — архитектурно-эстетически противно, да и также при каждом вызове функции надо будет их в регисры пропихивать.
Re[6]: Замена типа переменной long int на long long без вычислений замедляет код
От: Kubyshev Andrey  
Дата: 01.09.13 15:09
Оценка:
G>Какие ключи у вас стоят?

G>У меня для long long на x64 раскомментирование строчки:

G>
std::cout << "SizeOf(CalcBars) = " << std::endl;


G>дает замедление на 60%. На Win32 — в два раза.


Никакого замедления нет, ключи самые обычные, я ничего не менял.
/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

Пацаны, хорошь гадать на пустом месте, ниче не замедляется.
Re[7]: Замена типа переменной long int на long long без вычислений замедляет код
От: getch  
Дата: 01.09.13 15:18
Оценка:
Здравствуйте, 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 без вычислений замедляет код
От: cserg  
Дата: 01.09.13 16:46
Оценка:
Здравствуйте, getch, Вы писали:

Все у вас работает так как и должно. Магии здесь никакой нет. Замедление на 15% происходит, когда складываются 64 битные значения вместо 32 битных в цикле. Замедление в 2 раза происходит, когда inlining для Print отрубается после добавления cout перед циклом. В этом случае добавляется инструкция call в тело цикла. Проблема у вас в том, что цикл повторяется огромное число раз. Небольшое изменение в теле цикла сильно влияет на результат. Интересно, что это за задача такая в которой 100 млрд. итераций?
Re[15]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Кодт Россия  
Дата: 01.09.13 17:23
Оценка: +2
Здравствуйте, getch, Вы писали:

G>Ну а как без статиков тогда обойтись? Запихивать все на глобальный уровень — архитектурно-эстетически противно, да и также при каждом вызове функции надо будет их в регисры пропихивать.


Я без понятия, как обойтись без статиков в реальном коде, который я не видел.
А здесь можно выполнить ряд преобразований кода, который сведётся к тому, чтобы проинлайнить Print вручную, раз уж компилятор не захотел делать это сам.
И смысл? Ну, мы увидим, что 64-битная арифметика на 5 или 15% тормознутее 32-битной, и сделаем очевидный вывод: не использовать 64 бита без нужды.

Если нужна помощь в рефакторинге реального кода, так это... код в студию. Что-нибудь придумаем.
Перекуём баги на фичи!
Re[9]: Замена типа переменной long int на long long без вычислений замедляет код
От: getch  
Дата: 01.09.13 19:36
Оценка:
Здравствуйте, cserg, Вы писали:

C>Все у вас работает так как и должно. Магии здесь никакой нет. Замедление на 15% происходит, когда складываются 64 битные значения вместо 32 битных в цикле. Замедление в 2 раза происходит, когда inlining для Print отрубается после добавления cout перед циклом. В этом случае добавляется инструкция call в тело цикла. Проблема у вас в том, что цикл повторяется огромное число раз. Небольшое изменение в теле цикла сильно влияет на результат. Интересно, что это за задача такая в которой 100 млрд. итераций?


Странно просто, что компилятор делает call в цикле за вместо inlining Print. Как на это решение влияет cout перед циклом — не ясно. Но факт — влияет все же. Хотя ничто ему не мешает сделать все правильно.

100 млрд — это с потолка взятое число для примера. Но вообще подобное количество вычислений — далеко не редкость. Занимаюсь просто исследованием временных рядов. А там без огромных вычислений довольно туго, поэтому и облако и GPU в планах подключить. Многосуточные расчеты — обычное дело. Ну как и при мат. моделировании и расчетах физических свойств огромных по размерам сеток. Вообщем, задач загрузить под завязку даже суперкомрьютеры полно. Лишь бы не в лоб и со знанием дела.
Re[16]: Замена типа переменной long int на long long без вычислений замедляет ко
От: getch  
Дата: 01.09.13 19:39
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если нужна помощь в рефакторинге реального кода, так это... код в студию. Что-нибудь придумаем.


Спасибо за желание помочь. Достигну значимых результатов в своей области — не постесняюь, воспользуюсь вашим предложением.
Не все сразу.
Re[10]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Кодт Россия  
Дата: 04.09.13 16:43
Оценка:
Здравствуйте, getch, Вы писали:

G>Странно просто, что компилятор делает call в цикле за вместо inlining Print. Как на это решение влияет cout перед циклом — не ясно. Но факт — влияет все же. Хотя ничто ему не мешает сделать все правильно.


Может, ему сам факт cout<< не нравится.
Может, критическое значение имеет размер функции main: если она меньше порога по длине, или нагрузке на стек, или нагрузке на регистры, то инлайнит содержимое, а если больше порога — то заведомо не инлайнит.
Попробуй засунуть этот cout<< внутрь Print и посмотреть, проинлайнится он или нет.
Перекуём баги на фичи!
Re[11]: Замена типа переменной long int на long long без вычислений замедляет ко
От: getch  
Дата: 04.09.13 21:50
Оценка: -1
Здравствуйте, Кодт, Вы писали:

К>Может, ему сам факт cout<< не нравится.

К>Может, критическое значение имеет размер функции main: если она меньше порога по длине, или нагрузке на стек, или нагрузке на регистры, то инлайнит содержимое, а если больше порога — то заведомо не инлайнит.
К>Попробуй засунуть этот cout<< внутрь Print и посмотреть, проинлайнится он или нет.

Если поместить cout в Print (только ни к чему), то замедления не происходит. Вообщем, данное замедление — это просто баг, оправдание которому быть не может. Надеюсь, исправят.
Re[12]: Замена типа переменной long int на long long без вычислений замедляет ко
От: Кодт Россия  
Дата: 05.09.13 08:22
Оценка:
Здравствуйте, getch, Вы писали:

G>Если поместить cout в Print (только ни к чему), то замедления не происходит. Вообщем, данное замедление — это просто баг, оправдание которому быть не может. Надеюсь, исправят.


Это не баг, а "хочу фичу! хочухочухочу!"
Никто не обещает инлайнить функцию во что бы то ни стало. Даже __forceinline не даёт 100% гарантии.
Чёрт знает, по какой эвристике компилятор решил, что без cout инлайн возможен, а с ним — нет.

Кстати!!!! Баг у тебя, а не у компилятора.
Ты почему не написал inline void Print ??
Всё, тема закрыта.
Перекуём баги на фичи!
Re[13]: Замена типа переменной long int на long long без вычислений замедляет ко
От: getch  
Дата: 05.09.13 08:59
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Кстати!!!! Баг у тебя, а не у компилятора.

К>Ты почему не написал inline void Print ??
Потому что компилятор настроен так, чтобы инлайнить все, что только может. Дописал все же inline — замедление никуда не делось.

К>Всё, тема закрыта.

Согласен. Пусть тема остается, как простой пример явного бага оптимизатора компилятора.
Re[14]: Замена типа переменной long int на long long без вычислений замедляет ко
От: BulatZiganshin  
Дата: 05.10.13 00:36
Оценка:
Здравствуйте, getch, Вы писали:

G>Согласен. Пусть тема остается, как простой пример явного бага оптимизатора компилятора.


ага. ошибка в модуле чтения мыслей
Люди, я люблю вас! Будьте бдительны!!!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.