[Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 30.03.07 20:34
Оценка: 185 (32) -1

Exceptions vs. Return Values

Провёл на досуге исследование на тему сообщение об ошибках с помощью исключений против сообщения об ошибках с помощью возвращаемых значений с т.з. скорости выполнения кода и кодогенерации. Возможно кому-то ещё будет интересно.

Цель можно охарактеризовать примерно так: исследовать скорость работы некоторых ключевых паттернов кода, реализованных с применением исключений для сообщения об ошибках, или с помощью возвращаемых значений.

Простой случай

Что б не было скучно сразу начну с некоторых результатов.

rv (success) rv (fail) ex (success) ex (w/o try) ex (fail)
msvc71128 4 4 66928
msvc81284 417140
gcc411220 8 850476
gcc3241031267444
Сейчас поясню, что что значит.
rv (success) вызов функции, которая сообщает об ошибке с помощью возвращаемого значения (rv – return value). Функция возвращает значение, что ошибки не произошло – реально возвращается bool true. После вызова происходит проверка возвращаемого значения. Сама функция никакой работы не делает, т.е. пустая
rv (fail) аналогично предыдущему, только функция возвращает неудачу — false
ex (success) функция сообщает об ошибке с помощью исключения (ex — exception), соответственно её вызов обрамлён в try/catch. Функция исключение не кидает
ex (w/o try) аналогично предыдущему, только вызов функции не обрамлён в try/catch — что бы увидеть влияние входа/выхода в try блок
ex (fail) ex (success), только функция кидает исключение
msvc71 WinXP on Pentium4, msvc7.1
msvc8 WinXP on Pentium4, msvc8sp1
gcc41 MinGW on Pentium4, gcc4.1.1
gcc32 Linux2.4 on Pentium4, gcc3.2.3
Компилировал со всеми оптимизациями, при этом следил, чтобы исследуемые функции _не_ встраивались. Время замерял с помощью rdtsc, соответственно результаты приведены в тактах процессора. Каждый тест запускал 1000 раз, потом находил минимальный результат.
Сразу оговорюсь, что на полную объективность не претендую. Какие результаты получил в своих конкретных условиях, при определённых настройках компилятора и т.д., такие и привожу. Но тем не менее, уверен, что основные тенденции уловлены правильно. Тем более сгенерированный код во всех случаях изучался на правдоподобность.

Выводы

Выводы для такого тривиального случая с простыми функциями.

Исключения быстрее, когда реально исключения не кидаются. За счёт чего? За счёт дополнительных инструкций на проверку возвращаемого значения, и на переход (jmp).

Вход/выход в try блок [как ни странно] не влияет на производительность.

Кидание исключения очень дорого. Порядка 20мкс под Win/msvc71 и порядка 100мкс под Linux (почему так долго под Linux не знаю). А под msvc8 ухитрились сделать за 7мкс, хотя они всё равно реализованы поверх SEH.

Более интересный случай

В первом случае у исключений было небольшое приемущество, точнее немного неадекватный случай, т.к. программа не выделяла никаких ресурсов. Когда выделяются ресурсы для исключений начинается самое интересное, т.к. приходится помещать фреймы на стек, следить за созданием объектов и т.д. Теперь замерим скорость с ресурсами. Сразу поясню, что я подразумеваю под ресурсами. В условиях исключений под ресурсом подразумеваю объект класса с нетривиальным деструктором (в котором происходит освобождение ресурса) и с конструктором (который выделяет ресурс, при этом может провалиться и кинуть исключение). В условиях возвращаемых значений я рассмотрел 2 варианта. Первый – в стиле С++ — класс, в деструкторе также освобождает ресурс, а конструктор заменил на функцию bool init(), которая выделяет ресурс и сообщает о успешности. Второй вариант – в стиле С – ресурс представляет из себя некий int, и 2 функции int constructor(int*) и void destructor(int). Все функции выделения/освобождения ресурса сами по себе ничего не делают, кроме как вызываются.

Функции тестировал те же, только отличие в том, что функция в начале работы «выделяет» ресурс, потом «освобождает» ресурс и возвращается. Соответственно в присутствии исключений, т.к. у локального объекта есть деструктор, компилятору приходится создавать фреймы на стеке и т.д. Замерял только в «успешном» случае, т.к. если будет кидаться исключение, то уже понятно, что это будет настолько долго, что и сравнивать нечего.
Собственно результаты:
с с++/rvс++/ex
msvc71 242424
msvc8 242420
gcc41328884
gcc32263222
Для большей правдоподобности и интриги код в стиле С компилировал именно как С код, а не С++, соотв. пользовался не g++, а gcc.

Выводы

Выводы для случая с функциями с выделением ресурса.
Под msvc71 всё ровненько – даже не интерсно. Т.е. накладные расходы на проверки возвращаемых значений скомпенсировались накладными расходами на поддержку исключений.
gcc4.1.1 под mingw как-то совсем неадекватно себя ведёт при необходимости освобождать ресурсы... (почему так не знаю)
gcc3.2.2 под Linux – результаты примерно одинаковые. Только в С++ при использовании возвращаемых значений накладываются сразу 2 типа накладных расходов, поэтому получается значительно дольше.

Поведение в асимптотике

Теперь следующий тест. Очень много функций и очень много ресурсов. Чтобы поглядеть как ведёт себя производительность в асимптотике.
Функции такого вида:
F6()
{
повторить 6 раз // в коде это записано не в виде цикла, а развёрнуто
{
выделяем 6 ресурсов
вызываем F5();
}
}
Соответственно функция F5 аналогичная, только вызывает F4, и так далее. F0 – ничего не делает – сразу возвращается.
В С варианте это было записано примерно так:
int f6()
{
    int o1, o2;
    int res = 0;
    if (!constructor(&o1)) goto end;
    if (!constructor(&o2)) goto do1;
    if (!f5()) goto do2;
    res = 1;
    do2:    destructor(o2);
    do1:    destructor(o1);
    end:    return res;        
}

только экстраполировано на выделение 6 ресурсов и это всё повторяется 6 раз.
В варианте с++/rv:
bool f6()
{
    obj o1, o2;
    if (!o1.init()) return false;
    if (!o2.init()) return false;
    if (!f5()) return false;
    return true;
}

В варианте с++/ex:
bool f6()
{
    obj o1, o2;
    f5();
}


Результаты:
с с++/rvс++/ex
msvc71 636300462310606182104
msvc8 6361992 6258460 6181740
gcc41 9016944 9760084 9385664
gcc32 8510423 6640676 5545090

Выводы

Ну что тут можно сказать. В принципе код с исключениями немного быстрее, но совсем немного (но это уже приятно ). Единственное он медленнее на gcc41, но вообще как-то совсем неадекватно сгенерировал код...

Ещё тест


Ещё я проводил аналогичный тест, но во время выполнения эмулировал возникновение ошибки (либо кидалось исключение, либо возвращался false). Результаты для краткости приводить не буду. Но суть такая, что в данном случае код с исключениями всё равно остаётся быстрее, т.к. время работы функции очень большое и за ним время кидания исключения нивелируется.

Размер кода


Так же есть ещё один аспект, влияющий на производительность, но который ускользает при таких замерах – размер сгенерированного кода. Чем больше кода – тем больше промахов кэша и переходов через границы страницы памяти – это может достаточно сильно влиять на производительность. Соответственно я замерил размер кода для одной функции типа f6(), которые я приводил выше. Результаты:
с с++/rvс++/ex
instr 386 442 232
size 1320 2359 1329
Замерял на msvc71. instr – кол-во ассемблерных команд. Size – размер функции в байтах.

У исключений значительно меньше инструкций, тем не менее размер кода равен размеру кода на С с возвращаемыми значениями. Как ни странно... Связано с тем, что команды там больше по размеру. Код на С++ с возвращаемыми значениями тут сильно проигрывает – так там инструкции и на проверки возвращаемых значений и на поддержку исключений.

Тест без ресурсов


Так же провёл следующий тест. Функции аналогичные предыдущим, но не выделяются ресурсы – просто идёт много форвардов на другие функции, а те на другие и т.д.


с с++/rvс++/ex
msvc71 970404 746460 653144
msvc8 970404 746464 653144
gcc41 858432 858444 765124
gcc32 705457 633707 521712
Размер кода:
с с++/rvс++/ex
instr 22 21 6
size 59 58 25

Выводы

Тут картина уже интереснее – исключения значительно вырываются вперёд. На msvc на 50% (!) на gcc на 35% (!). По размеру код на 136% (!).
Тут можно сделать важный вывод – если есть функции, в которых нет локальных переменных/аргументов с нетривиальными деструкторами – при использовании исключений они будут работать до 50% быстрее и размер кода будет меньше до 136%.

smart_ptr vs. smart_ptr&

Попутно я исследовал следующий вопрос – имеет ли смысл передавать умные указатели по ссылке вместо передачи по значению. Мы зачастую (ну я по-крайней мере ) передаю просто boost::shared_ptr без ссылок – по значению.
Функции аналогичные функциям из предыдущего теста – просто много форвардинга вызовов функций, без выделения ресурсов, но при этом между функцими передавался один boost::intrusive_ptr, в одном случае по значению, в другом по ссылке.


boost::intrusive_ptr boost::intrusive_ptr
msvc71 2226100 746492
msvc8 2237212 746492
gcc41 3153288 783844
gcc32 2301066 550930
Размер кода:
boost::intrusive_ptr boost::intrusive_ptr
instr 76 17
size 231 45

Выводы

Разница поразительная. При передаче по ссылке скорость выросла в 4.18 раза, размер кода уменьшился в 5.13 раза. Накладные расходы идут не только на увеличения/уменьшения счётчика, но так же на поддержание фрейма на стеке, и на контроль конструирования объектов – что бы знать какие рушить при исключении.

Более реалистичный тест

Более реалистичный тест по количеству ресурсов и вызовов функций. С исключениями тестовые функции выглядят так:
void f6()
{
  obj o1, o2, o3;
  f5();
  f5();
}

f5() выглядит аналогично, только вызывает f4() и т.д. f0 ничего не делает. Код с возвращаемыми значениями аналогичный, только... переписан соответственно с возвращаемыми значениями. Получается 64 вызова самой вложенной функции и примерно 200 объектов с деструкторами на тест, что более менее сравнимо с некой функциональностью в современной программе.
Смотрим, что получилось:


с с++/rvс++/ex
msvc71 4772 4804 4652
msvc8 4768 4792 4704
gcc41 7604 9924 8924
gcc32 5510 5127 4451
Тут получается, что исключения чуточку впереди (не считая gcc41 под mingw, который опять неадекватно сгенерировал код).

Далее сделал следующее – из 100 вызовов функции 1 проваливается (кидается исключение, или возвращается код возврата с ошибкой), и я беру не менимальное из всех замеров время, а усредняю по всем 100 замерам. Т.о. эмулируется ситуация, что в программе иногда происходит ошибка.
Смотрим, что получилось:


с с++/rvс++/ex
msvc71 4816 5195 4946
msvc8 4813 5384 4843
gcc41 7682 10059 9276
gcc32 5976 5135 7505
Тут уже видно, что исключения и возвращаемые значения практически сравнялись – где-то уже немного отстали, где-то уже почти отстали. Соответственно, если увеличивать процент провалов, то исключения уже начнут существенно отставать.

Выводы

Общие выводы какие возникли – возвращаемые значения типа писсимистической стратегии – т.е. чуть что сделали сразу проверяем, а не плохо ли всё, исключения – оптимистическая стратегия – делаем всё подряд без разбора и проверок, авось всё хорошо.
В принципе возникает такое ощущение, что исключения всё-таки немного быстрее (если не происходит ошибок). Соответственно если для какой-то функции вероятность провала более 1%, то надо использовать коды возврата, если менее 1%, то надо использовать исключения для повышения производительности. Да-да, вы не ослышались – для поднятия производительности надо использовать исключения.
Так же стоит отметить, что в msvc8 по сравнению с msvc71 резко снизилась стоимость кидания исключения. Но тут у них есть предел, т.к. исключения реализованы поверх SEH, значит кидание исключения всегда будет связано с переходом в ядро.
Хочется ожидать большего от gcc, т.к. они не ограничены этим фактором и могут сделать действительно быстрые исключения. Сейчас уже есть некоторые исследования на тему реализации быстрых исключений, будем надеятся, что их воплотят в gcc в ближайшем будущем. Тогда чаша весов ещё более сильно перевесит в сторону исключений.
Так же совершенна непонятна ситуация с gcc4.1.1/mingw – и кодогенерация какая-то непонятная и исключения ооочень медленные.
Так же очевидно, что использование возвращаемых значений под С++ — это совсем плохая идея – издержки от двух стихий, а плюсов нет в противопоставление с возвращаемыми значениями под С.
Ещё момент — при использовании исключений принципиально различается кодогенерация в зависимости от того, есть ли в функции локальные объекты/аргументы с нетривиальными деструкторами — если нет, то просто идут вызовы других функций, если есть, то тут уже начинается: занесение фрейма на стек, подсчёт сконструированных объектов, снятие фрейма со стека. Получается значительная разница и по скорости и по размеру кода.

Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: [Investigation] Exceptions vs. Return Values
От: Сергей Мухин Россия  
Дата: 31.03.07 05:44
Оценка:
Здравствуйте, remark, Вы писали:

работа проделана большая,

R>

Выводы

R>Общие выводы какие возникли – возвращаемые значения типа писсимистической стратегии – т.е. чуть что сделали сразу проверяем, а не плохо ли всё, исключения – оптимистическая стратегия – делаем всё подряд без разбора и проверок, авось всё хорошо.

Наоборот, при кидании исключения мы никогда не пройдем мимо ошибок (если конечно catch(...) не использовать). И будем обрабатывать ошибку на том уровне, на которм надо, а в случае возрата, нам еще надо передать управление на другой уровень, если обработка идет там.

R>В принципе возникает такое ощущение, что исключения всё-таки немного быстрее (если не происходит ошибок). Соответственно если для какой-то функции вероятность провала более 1%, то надо использовать коды возврата, если менее 1%, то надо использовать исключения для повышения производительности. Да-да, вы не ослышались – для поднятия производительности надо использовать исключения.


1% это очень много. Изначально использовал исключения и не сомневался, в этом. В обработке ошибок производительность занимает далеко не первое место.

R>Так же стоит отметить, что в msvc8 по сравнению с msvc71 резко снизилась стоимость кидания исключения. Но тут у них есть предел, т.к. исключения реализованы поверх SEH, значит кидание исключения всегда будет связано с переходом в ядро.


SEH для С++ с ядром не имеет ничего общего. Это всего лишь цепочка блоков. Вряд ли исключения изменились, возможно оптимизировали деструктор или вызовы его уменьшили. или FPO оптимизацию подняли.

R>Так же очевидно, что использование возвращаемых значений под С++ — это совсем плохая идея – издержки от двух стихий, а плюсов нет в противопоставление с возвращаемыми значениями под С.

R>Ещё момент — при использовании исключений принципиально различается кодогенерация в зависимости от того, есть ли в функции локальные объекты/аргументы с нетривиальными деструкторами — если нет, то просто идут вызовы других функций, если есть, то тут уже начинается: занесение фрейма на стек, подсчёт сконструированных объектов, снятие фрейма со стека. Получается значительная разница и по скорости и по размеру кода.
---
С уважением,
Сергей Мухин
Re: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 31.03.07 08:32
Оценка:
Здравствуйте, remark, Вы писали:

.....
R>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.

R>


1. Спасибо за проделаную работу. Я никогда не понимал , почему так распросранен миф среди С++ программистов , о "накладности" исключений. Это же очевидно что их импдементацию можно сделать не накладнее чем коды возврата. Но с учетом того что создатели компилятора могут использовать нетривиальные трюки.


2. Спасибо за исследование размера кода , это тоже один из мифов.


3. Не исследован случай когда идет передача кода возврата на несколько уровней вверх (хотя бы на три).


4. Самый большой недостакок и пожалуй единственный , а где код ? Думаю тут найдутся люди, которые помогут его причесать.


5. А после некоторого обсуждения на форуме , не написал бы ты статью с асемблерными листингами ?


6. Очень интересен анал хотя бы под одну embeded платформу.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: [Investigation] Exceptions vs. Return Values
От: Left2 Украина  
Дата: 31.03.07 12:13
Оценка: +1 :)
M>6. Очень интересен анал хотя бы под одну embeded платформу.

Несмотря на явную двусмысленность этого предложения , абсолютно полностью согласен с тем что было бы крайне интересно исследовать не-x86 процессоры, особенно — ARMы и иже с ними.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 31.03.07 12:39
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, remark, Вы писали:


СМ>работа проделана большая,


R>>

Выводы

R>>Общие выводы какие возникли – возвращаемые значения типа писсимистической стратегии – т.е. чуть что сделали сразу проверяем, а не плохо ли всё, исключения – оптимистическая стратегия – делаем всё подряд без разбора и проверок, авось всё хорошо.

СМ>Наоборот, при кидании исключения мы никогда не пройдем мимо ошибок (если конечно catch(...) не использовать). И будем обрабатывать ошибку на том уровне, на которм надо, а в случае возрата, нам еще надо передать управление на другой уровень, если обработка идет там.


Полностью согласен, тем не менее не понимаю, к чему относится "Наоборот"...

R>>В принципе возникает такое ощущение, что исключения всё-таки немного быстрее (если не происходит ошибок). Соответственно если для какой-то функции вероятность провала более 1%, то надо использовать коды возврата, если менее 1%, то надо использовать исключения для повышения производительности. Да-да, вы не ослышались – для поднятия производительности надо использовать исключения.


СМ>1% это очень много. Изначально использовал исключения и не сомневался, в этом. В обработке ошибок производительность занимает далеко не первое место.


Да, 1% это много. Сервера зачастую обрабатывают тысячи, десятки тысяч, сотни тысяч... транзакций без ошибок.
Тем не менее такие данные мне лично помогут более точно ориентироваться. А именно — допустим на сетевой сервер поступают некие "заявки". Если заявки приходят из доверенного источника и по надежному каналу, то типа как ошибок в данных быть не должно (ну то есть они бывают допустим в 0.001%) тут однозначно можно использовать исключения при валидации заявки. Если же заявки приходят от недоверенных источников и статистика такая, что ошибки при валидации заявки бывают в 5% случаев — т.е. "шлют всякую фигню" образно выражаясь — можно подумать о возвращаемом значении при валидации — иначе обработка ошибок для некорректных заявок может снизить пропускную способность и для корректных заявок.


R>>Так же стоит отметить, что в msvc8 по сравнению с msvc71 резко снизилась стоимость кидания исключения. Но тут у них есть предел, т.к. исключения реализованы поверх SEH, значит кидание исключения всегда будет связано с переходом в ядро.


СМ>SEH для С++ с ядром не имеет ничего общего. Это всего лишь цепочка блоков. Вряд ли исключения изменились, возможно оптимизировали деструктор или вызовы его уменьшили. или FPO оптимизацию подняли.


Тут я возможно ступил, у меня почему-то подсознательно SEH ассоциировался с ядром — надо будет ещё продебажить... хотя вроде я там видел переход в ядро... ладно ещё уточню...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: [Investigation] Exceptions vs. Return Values
От: superlexx  
Дата: 31.03.07 12:45
Оценка:
Здравствуйте, remark, Вы писали:

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


забыли сравнить с С++ кодом, генерированным без поддержки исключений

отключение поддержки исключений при генерации OS (WinCE 5.0, ARMV4I) экономит между прочим около 400кБ, так что здесь не всё так однозначно.
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 31.03.07 12:55
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Здравствуйте, remark, Вы писали:


M>.....

R>>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.

R>>


M>1. Спасибо за проделаную работу. Я никогда не понимал , почему так распросранен миф среди С++ программистов , о "накладности" исключений. Это же очевидно что их импдементацию можно сделать не накладнее чем коды возврата. Но с учетом того что создатели компилятора могут использовать нетривиальные трюки.


Да, тут сейчас какая-то двойственность получается — если исключения не летят, то они на сколько-то быстрее, а если летят, то значительно медленнее. Тем не менее я не понимаю, почему кидание такое медленное. И я уверен, что тут есть простор для оптимизации и в будущем это будет _значительно_ быстрее.


M>2. Спасибо за исследование размера кода, это тоже один из мифов.


То, что меня удивило, что С код такой же по размеру, несмотря на то, что инструкций там значительно больше... но это если есть "ресурсы", если нет, то С код значительно больше.


M>3. Не исследован случай когда идет передача кода возврата на несколько уровней вверх (хотя бы на три).


А неважно, всё равно кидание будет значительно медленнее.


M>4. Самый большой недостакок и пожалуй единственный , а где код ? Думаю тут найдутся люди, которые помогут его причесать.


Ну там куски кода для случая с "ресурсами" я приводил. Я думаю, что там можно представить как он выглядел. Дело в том, что его очень много и реально он описан на макросах... поэтому там не особо есть что приводить.
Что я понял уже когда я это всё доделал, что надо было код не кустарным способом делать, а сделать генератор кода, которому задаёшь параметр — кол-во "ресурсов, кол-во уровней вызовов и т.д. и что бы он генерировал много красивого кода. И снабдить это ещё скриптами для автоматической сборки и что бы результаты выводились сразу в виде красивых табличек. Тогда бы я это выложил и все желающие запускали бы это на своих платформах и потом выкладывали бы сюда свои результаты... тогда и для ARM'ов бы можно было протестировать и более точно проследить зависимости скорости/размера кода от различных параметров типа кол-ва "ресурсов".


M>5. А после некоторого обсуждения на форуме , не написал бы ты статью с асемблерными листингами ?


Теоретически можно, я об этом думал, даже когда-то давно скачивал пак для написания статей. Но всё же времени это потребует значительно больше.

M>6. Очень интересен анал хотя бы под одну embeded платформу.


К сожалению это не ко мне. Может руки дойдут это оформить в виде набора файлов, который можно запустить на своей платформе и выложить результаты...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 31.03.07 12:56
Оценка: :)
Здравствуйте, Left2, Вы писали:

M>>6. Очень интересен анал


L>Несмотря на явную двусмысленность этого предложения ,


Да, я тоже вначале смутился



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: [Investigation] Exceptions vs. Return Values
От: Vain Россия google.ru
Дата: 31.03.07 13:00
Оценка:
Здравствуйте, remark, Вы писали:

R>

Exceptions vs. Return Values

Интересно бы было ещё узнать статистику для retv в стиле Win32 SetLastError/GetLastError, имхо тоже было бы полезно.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 31.03.07 13:01
Оценка:
Здравствуйте, superlexx, Вы писали:

S>Здравствуйте, remark, Вы писали:


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


S>забыли сравнить с С++ кодом, генерированным без поддержки исключений


Я думаю, что это будет аналогично С коду. Единственное отличие — функции освобождения ресурсов будут вызываться неявно, но всё равно в тех же местах, где они в С коде вызываются явно.
Тем более я такую настройку лично не уважаю Т.к. получается, что нельзя использовать конструкторы, операторы и т.д.


S>отключение поддержки исключений при генерации OS (WinCE 5.0, ARMV4I) экономит между прочим около 400кБ, так что здесь не всё так однозначно.


А WinCE можно сгенерировать из исходников???



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [Investigation] Exceptions vs. Return Values
От: Left2 Украина  
Дата: 31.03.07 13:12
Оценка:
R>А WinCE можно сгенерировать из исходников???

Там часть кода компилируется при билде системы, часть — линкуется из предоткомпилированных под конкретный проц библиотек.
Так что собрать под какой-то свой проц — не получится, только под те что поддерживаются MS.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 31.03.07 14:38
Оценка: 1 (1) +2 -1
R>Провёл на досуге исследование на тему сообщение об ошибках с помощью исключений против сообщения об ошибках с помощью возвращаемых значений с т.з. скорости выполнения кода и кодогенерации. Возможно кому-то ещё будет интересно.

Во-первых, нужен исходный код. А во-вторых, все зависит от величины прослойки, которая ведет к функции api. В зависимости от типа кода она будет разной. Если очень тонкой — тогда исключения просто не могут быть быстрее ввиду того, что функции апи используют возвращаемые значение, которые необходимо будет транслировать в исключения ровно такой же проверкой. Если же, наоборот, задача исключительно вычислительная — тогда конечно, исключения могут и выигрывать. В общем, все зависит от типа задачи, а такие тесты — средняя температура по больнице, которая ни о чем не говорит, на мой взгляд.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: [Investigation] Exceptions vs. Return Values
От: Сергей Мухин Россия  
Дата: 31.03.07 17:36
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Сергей Мухин, Вы писали:


R>Полностью согласен, тем не менее не понимаю, к чему относится "Наоборот"...


"наоборот" относится к фразе "делаем всё подряд без разбора и проверок, авось всё хорошо" т.к. по этой фразе можно понять, что исключения позволяют писать код в которм ошибки так и шастают а программист об этом и не знает.
---
С уважением,
Сергей Мухин
Re[3]: [Investigation] Exceptions vs. Return Values
От: Сергей Мухин Россия  
Дата: 31.03.07 17:39
Оценка: 9 (1)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Сергей Мухин, Вы писали:


СМ>>SEH для С++ с ядром не имеет ничего общего. Это всего лишь цепочка блоков. Вряд ли исключения изменились, возможно оптимизировали деструктор или вызовы его уменьшили. или FPO оптимизацию подняли.


R>Тут я возможно ступил, у меня почему-то подсознательно SEH ассоциировался с ядром — надо будет ещё продебажить... хотя вроде я там видел переход в ядро... ладно ещё уточню...


вот хорошая стаья про SEH здесь
---
С уважением,
Сергей Мухин
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 01.04.07 05:43
Оценка: +1
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, remark, Вы писали:


R>>

Exceptions vs. Return Values

V>Интересно бы было ещё узнать статистику для retv в стиле Win32 SetLastError/GetLastError, имхо тоже было бы полезно.

Это уже просто надстройка над возвращаемыми значениями. В успешном случае производительность будет равна производительности с возвращаемыми значениями, а когда происходят ошибки, то добавляется небольшое пенальти на вызов функций SetLastError/GetLastError, но оно, конечно, не сравнимо с киданием исключений. Т.ч. я думаю, тут ничего принципиально не изменится.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 01.04.07 15:19
Оценка:
Здравствуйте, Andrew S, Вы писали:

R>>Провёл на досуге исследование на тему сообщение об ошибках с помощью исключений против сообщения об ошибках с помощью возвращаемых значений с т.з. скорости выполнения кода и кодогенерации. Возможно кому-то ещё будет интересно.


AS>Во-первых, нужен исходный код.


Он там есть для случая с выделением "ресурса". Тривиальные случаи, я думал, не вызовут вопросов.
Пустая функция с возвращаемым значением выглядела вот так:
bool f()
{
  return true;
}


Вызывалась вот так:

if (!f())
  ++error_count;


Пустая функция с исключениями выглядела вот так:
void f()
{
}


Вызывалась вот так:

try
{
  f();
}
catch (...)
{
  ++error_count;
}




AS>А во-вторых, все зависит от величины прослойки, которая ведет к функции api.


Влияние именно этой величины я и исследовал. Т.е. вначале смотрел, когда эта величина 1 (функция), потом в асимптотическом случае, когда очень много функций, потом в случае, когда величина прослойки более-менее соизмерима с неким реальным проектом.
В принципе у меня есть идея на будущее сделать генератор кода и построить графики производительности в зависимости от "глубины" прослойки, "ширины" прослойки и кол-ва "ресурсов", которые выделяются в прослойке. Но пока получилось только так.

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


Это всё есть. Если прослойка 0 — то одинаково, т.к ничего не различается. Если 1 — то исключения быстрее, Если много — то исключения ещё быстрее. Правда ситуация меняется, когда есть "ресурсы".


AS>Если же, наоборот, задача исключительно вычислительная — тогда конечно, исключения могут и выигрывать. В общем, все зависит от типа задачи, а такие тесты — средняя температура по больнице, которая ни о чем не говорит, на мой взгляд.


Естественно всё зависит от задачи. Но я то исследовал не задачи, а примитивы. Вычислительную сложность которых можно просто складывать и оценить результат.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [Investigation] Exceptions vs. Return Values
От: Vain Россия google.ru
Дата: 01.04.07 18:10
Оценка:
Здравствуйте, remark, Вы писали:

R>>>

Exceptions vs. Return Values

V>>Интересно бы было ещё узнать статистику для retv в стиле Win32 SetLastError/GetLastError, имхо тоже было бы полезно.

R>Это уже просто надстройка над возвращаемыми значениями. В успешном случае производительность будет равна производительности с возвращаемыми значениями, а когда происходят ошибки, то добавляется небольшое пенальти на вызов функций SetLastError/GetLastError, но оно, конечно, не сравнимо с киданием исключений. Т.ч. я думаю, тут ничего принципиально не изменится.


Я имею ввиду ещё и использование TLS

R>
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: [Investigation] Exceptions vs. Return Values
От: MShura  
Дата: 01.04.07 18:21
Оценка: 1 (1)
R>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.

В gcc для оптимизации jmp можно использовать макросы likely/unlikely.
А для msvc эти макросы можно сделать пустышками.
Re[2]: [Investigation] Exceptions vs. Return Values
От: Сергей Мухин Россия  
Дата: 01.04.07 18:58
Оценка:
Здравствуйте, MShura, Вы писали:

R>>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.


MS>В gcc для оптимизации jmp можно использовать макросы likely/unlikely.

MS>А для msvc эти макросы можно сделать пустышками.

и какое это имеет отношение к subj?
---
С уважением,
Сергей Мухин
Re[3]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 01.04.07 22:59
Оценка: +1
R>Вызывалась вот так:

R>
R>try
R>{
R>  f();
R>}
R>catch (...)
R>{
R>  ++error_count;
R>}
R>


AS>>А во-вторых, все зависит от величины прослойки, которая ведет к функции api.


R>Влияние именно этой величины я и исследовал. Т.е. вначале смотрел, когда эта величина 1 (функция), потом в асимптотическом случае, когда очень много функций, потом в случае, когда величина прослойки более-менее соизмерима с неким реальным проектом.

R>В принципе у меня есть идея на будущее сделать генератор кода и построить графики производительности в зависимости от "глубины" прослойки, "ширины" прослойки и кол-ва "ресурсов", которые выделяются в прослойке. Но пока получилось только так.

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


R>Это всё есть. Если прослойка 0 — то одинаково, т.к ничего не различается. Если 1 — то исключения быстрее, Если много — то исключения ещё быстрее. Правда ситуация меняется, когда есть "ресурсы".


Вот тут надо осторожнее в смысле организации цикла. Оптимизирующий компилятор вполне способен вынести установку фрейма исключений в "пустых" функциях за пределы цикла (тогда как для "нормальных" функций и тем более функций апи он этого делать не имеет права) — соответственно, такие тесты покажут фикцию. Как я понимаю, ты называешь эту ситуацию "ресурсы" (вообще, надо бы использовать нормальную терминологию — например, стек фрейм локальных переменных), тогда как на самом деле это вполне обычные локальные переменные — т.е. требование наличия своего стек фрейма, что скорее правило, а не исключение. В общем, надо моделировать _реальный_ код, а не пустые функции. А для этого надо иметь статистику по виду и функциональности функций. У тебя таковая есть?
А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга. Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки (особенно с учетом работающего механизма предсказания переходов). Поэтому обычно и стараются вынести это за пределы цикла — тогда, если код _только_ вычислительный, или же "толстая" прослойка до финальной функции (где проверка и генерация исключения) получится выигрыш. В общем, нужно нечто вроде fctest — где есть реальные паттерны работы дисковой подсистемы, поэтому и результаты реальны. А так — все это сферический конь в вакууме.

AS>>Если же, наоборот, задача исключительно вычислительная — тогда конечно, исключения могут и выигрывать. В общем, все зависит от типа задачи, а такие тесты — средняя температура по больнице, которая ни о чем не говорит, на мой взгляд.


R>Естественно всё зависит от задачи. Но я то исследовал не задачи, а примитивы. Вычислительную сложность которых можно просто складывать и оценить результат.


Не все так просто. Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора. В случае многозадачной системы это как минимум неверно. Выложи исходники — я тебя уверяю, народ раскритикует по самые В общем, для начала неплохо бы тебе разобраться в механизме функционирования всего этого на самом низком уровне (тем более, даже для разных компиляторов он отличается — например, 6, 7.1 и 8 имеют разные механизмы раскрутки фрейма исключений), а потом уже, вооружившись знаниями о том, что и как делает компилятор (а также и ОС), писать паттерны поведения. Тогда бы действительно получилось интересное исследование на тему.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: [Investigation] Exceptions vs. Return Values
От: Сергей Мухин Россия  
Дата: 02.04.07 04:31
Оценка:
Здравствуйте, Andrew S, Вы писали:


AS>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга. Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки (особенно с учетом работающего механизма предсказания переходов).


на вскидку — установка фрейма пара команд, ну мб три. снятие еще пара. и БЕЗ переходов. а вот проверка та же пара, но с переходом да и установка еще одна (в самой ф-ии). (это на I86). Итого 4(5) против 3.

я уже написал "проделана большая работа". т.е. измерялось только как определяется какие деструкторы надо вызвать — какие нет.

Поэтому обычно и стараются вынести это за пределы цикла — тогда, если код _только_ вычислительный, или же "толстая" прослойка до финальной функции (где проверка и генерация исключения) получится выигрыш. В общем, нужно нечто вроде fctest — где есть реальные паттерны работы дисковой подсистемы, поэтому и результаты реальны. А так — все это сферический конь в вакууме.

AS>>>Если же, наоборот, задача исключительно вычислительная — тогда конечно, исключения могут и выигрывать. В общем, все зависит от типа задачи, а такие тесты — средняя температура по больнице, которая ни о чем не говорит, на мой взгляд.

ть и оценить результат.

AS>Не все так просто. Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора. В случае многозадачной системы это как минимум неверно. Выложи исходники — я тебя уверяю, народ раскритикует по самые


согласен
---
С уважением,
Сергей Мухин
Re[3]: [Investigation] Exceptions vs. Return Values
От: MShura  
Дата: 02.04.07 05:54
Оценка:
R>>>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.

MS>>В gcc для оптимизации jmp можно использовать макросы likely/unlikely.

MS>>А для msvc эти макросы можно сделать пустышками.

СМ>и какое это имеет отношение к subj?


Я выделил отношение.
Я не проверял количественное влияние этих макросов, но ядерщики linux советуют использовать их использовать.

Если используются rv, то ветку (условие) обрабатывающую ошибку можно считать unlikely.

Например ошибку выделения памяти можно считать маловероятной
void *p = malloc( 1024 );
if ( unlikely(!p) )
  return -ENOMEM;


P.S. Я ядре 2.6.19 было насчитано порядка 5400 использований этих макросов
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 07:19
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, remark, Вы писали:


R>>>>

Exceptions vs. Return Values

V>>>Интересно бы было ещё узнать статистику для retv в стиле Win32 SetLastError/GetLastError, имхо тоже было бы полезно.

R>>Это уже просто надстройка над возвращаемыми значениями. В успешном случае производительность будет равна производительности с возвращаемыми значениями, а когда происходят ошибки, то добавляется небольшое пенальти на вызов функций SetLastError/GetLastError, но оно, конечно, не сравнимо с киданием исключений. Т.ч. я думаю, тут ничего принципиально не изменится.


V>Я имею ввиду ещё и использование TLS


TLS очень быстро — одно косвенное обращение — несколько тактов. С исключениями ни в какое сравнение всё равно не идёт.

R>>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 07:25
Оценка:
Здравствуйте, MShura, Вы писали:

R>>>>Ну вот собственно всё, что хотелось сказать. Коменты и замечания преведствуются Особенно интересно было бы услышать, если я пропустил какие-то важные аспекты в исследовании, которые могут сущуственно сказаться на производительности/размере кода/или ещё чём-то в разрезе исключения/возвращаемые значения.


MS>>>В gcc для оптимизации jmp можно использовать макросы likely/unlikely.

MS>>>А для msvc эти макросы можно сделать пустышками.

СМ>>и какое это имеет отношение к subj?


MS>Я выделил отношение.


Естественно, я запускал код не один раз. Я запускал код минимум тысячу раз и брал _минимальное_. Т.е. это время с учётом прогрева всех кэшей и бранч-предиктора. Т.ч. я не думаю, что это как-то повлияет на результат.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 07:26
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, remark, Вы писали:


R>>Здравствуйте, Сергей Мухин, Вы писали:


СМ>>>SEH для С++ с ядром не имеет ничего общего. Это всего лишь цепочка блоков. Вряд ли исключения изменились, возможно оптимизировали деструктор или вызовы его уменьшили. или FPO оптимизацию подняли.


R>>Тут я возможно ступил, у меня почему-то подсознательно SEH ассоциировался с ядром — надо будет ещё продебажить... хотя вроде я там видел переход в ядро... ладно ещё уточню...


СМ>вот хорошая стаья про SEH здесь


Спасибо, погляжу.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 07:32
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>на вскидку — установка фрейма пара команд, ну мб три. снятие еще пара. и БЕЗ переходов. а вот проверка та же пара, но с переходом да и установка еще одна (в самой ф-ии). (это на I86). Итого 4(5) против 3.

Насколько я лазил по коду, генерируемому ICC, почти везде где можно он использует cmov
так что с переходами тут тоже не все ясно...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 07:32
Оценка: 1 (1) +1
Здравствуйте, Andrew S, Вы писали:

AS>Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора.

Увы, но более точного метода измерения кроме как
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

и rdtsc пока ИМХО никто не предложил...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 07:45
Оценка:
Здравствуйте, Andrew S, Вы писали:


AS>Вот тут надо осторожнее в смысле организации цикла. Оптимизирующий компилятор вполне способен вынести установку фрейма исключений в "пустых" функциях за пределы цикла


Непонятно — в "пустых" функциях не устанавливается фрейм исключений...


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


Нет, под "ресурсами" я подразумеваю не просто локальные переменные, а локальные переменные с нетривиальным деструктором, если в терминах с++ или локальную переменную, для которой надо вызвать destructor() перед выходом из функции, если в терминах с.
Просто локальные переменные в данном контексте имхо не интересны, т.к. всё влияние будет заключаться в одной инструкции увеличении указателя стека, причём и в С и в С++.

AS>В общем, надо моделировать _реальный_ код, а не пустые функции. А для этого надо иметь статистику по виду и функциональности AS>функций. У тебя таковая есть?


Такая задача не ставилась, т.к. это будет очень серьёзное исследование. И имхо оно здесь не надо, т.к. я исследовал примитивы, вычислительную сложность можно просто сложить для получения результата.

AS>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга.

AS>
AS>Не был бы так однозначен. По крайней мере кол-во инструкций и время выполнения связаны не линейно.
Тем более я, как инженер, больше верю своим глазам


AS>Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки


Почему? Там не более 2-3 инструкций.

AS>(особенно с учетом работающего механизма предсказания переходов). Поэтому обычно и стараются вынести это за пределы цикла — тогда, если код _только_ вычислительный, или же "толстая" прослойка до финальной функции (где проверка и генерация исключения) получится выигрыш.


Может быть ты приведёшь какие-то замеры Мои замеры пока показывают обратную картину....


AS>В общем, нужно нечто вроде fctest — где есть реальные паттерны работы дисковой подсистемы, поэтому и результаты реальны. А так — все это сферический конь в вакууме.


Я всё же пока не вижу такой необходимости.


AS>>>Если же, наоборот, задача исключительно вычислительная — тогда конечно, исключения могут и выигрывать. В общем, все зависит от типа задачи, а такие тесты — средняя температура по больнице, которая ни о чем не говорит, на мой взгляд.


R>>Естественно всё зависит от задачи. Но я то исследовал не задачи, а примитивы. Вычислительную сложность которых можно просто складывать и оценить результат.


AS>Не все так просто. Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора. В случае многозадачной системы это как минимум неверно.


Не было никакой "многозадачной системы" и время я брал минимальное за много выполнений.
Это время не менялось от запуска к запуску. Имхо ты говоришь что-то не то...

AS>Выложи исходники — я тебя уверяю, народ раскритикует по самые


Код чего интересует?
Сами тестируемые функции? Или что?

AS>В общем, для начала неплохо бы тебе разобраться в механизме функционирования всего этого на самом низком уровне




AS>(тем более, даже для разных компиляторов он отличается — например, 6, 7.1 и 8 имеют разные механизмы раскрутки фрейма исключений),




AS>а потом уже, вооружившись знаниями о том, что и как делает компилятор (а также и ОС), писать паттерны поведения.




AS>Тогда бы действительно получилось интересное исследование на тему.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:03
Оценка: 1 (1) +1
AS>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга. Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки (особенно с учетом работающего механизма предсказания переходов).

СМ>на вскидку — установка фрейма пара команд, ну мб три. снятие еще пара. и БЕЗ переходов. а вот проверка та же пара, но с переходом да и установка еще одна (в самой ф-ии). (это на I86). Итого 4(5) против 3.


Установка фрейма. Вот типичный вариант (часть команд создания стек фрейма я включил сознательно, об этом ниже):

    mov    ebp, esp
    push    -1
    push    $callback
    mov    eax, DWORD PTR fs:__except_list
    push    eax
    mov    DWORD PTR fs:__except_list, esp


1. Команды работы с памятью (за исключением одной)
2. Размеры команд
3. Префиксы (поскольку используется FS)
4. Ведет к ebp-based стек фрейму. Т.е. минус один регистр. Как это важно на х86 — думаю, объяснять не надо.

Это все тянет тактов на 20-30 минимум (а на деле будет прилично больше). Про раскрутку мы не говорим — там кода в разы больше (в случае вин32), начиная от отработки исключения с переходом в KM и обратно, до собственно функции раскрутки, сначала самой ОС и потом уже stdlib. В общем, все не так тривиально, как тут пытаются показать — вплоть до влияния на производительность _самой_ функции, а не только окружения, которое ее вызывает.

Собственно, сама реализация всего этого в том же VC вызывает кучу вопросов — например, зачем было вообще пользоваться средствами OS для реализации software-only исключений.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:14
Оценка:
AS>>Вот тут надо осторожнее в смысле организации цикла. Оптимизирующий компилятор вполне способен вынести установку фрейма исключений в "пустых" функциях за пределы цикла

R>Непонятно — в "пустых" функциях не устанавливается фрейм исключений...


Ну и зачем это тогда тестировать?

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


AS>>В общем, надо моделировать _реальный_ код, а не пустые функции. А для этого надо иметь статистику по виду и функциональности AS>функций. У тебя таковая есть?


R>Такая задача не ставилась, т.к. это будет очень серьёзное исследование. И имхо оно здесь не надо, т.к. я исследовал примитивы, вычислительную сложность можно просто сложить для получения результата.


Понятно. Дальше можно не продолжать.

AS>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга.

AS>>
AS>>Не был бы так однозначен. По крайней мере кол-во инструкций и время выполнения связаны не линейно.
R>Тем более я, как инженер, больше верю своим глазам

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

AS>>Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки


R>Почему? Там не более 2-3 инструкций.


Наивно... Ты посмотри, _какие_ там инструкции.

AS>>(особенно с учетом работающего механизма предсказания переходов). Поэтому обычно и стараются вынести это за пределы цикла — тогда, если код _только_ вычислительный, или же "толстая" прослойка до финальной функции (где проверка и генерация исключения) получится выигрыш.


R>Может быть ты приведёшь какие-то замеры Мои замеры пока показывают обратную картину....


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


AS>>Не все так просто. Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора. В случае многозадачной системы это как минимум неверно.


R>Не было никакой "многозадачной системы" и время я брал минимальное за много выполнений.

R>Это время не менялось от запуска к запуску. Имхо ты говоришь что-то не то...

Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.

AS>>Выложи исходники — я тебя уверяю, народ раскритикует по самые


R>Код чего интересует?

R>Сами тестируемые функции? Или что?

Все — полный тест юнит.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 08:32
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>Вот тут надо осторожнее в смысле организации цикла. Оптимизирующий компилятор вполне способен вынести установку фрейма исключений в "пустых" функциях за пределы цикла


R>>Непонятно — в "пустых" функциях не устанавливается фрейм исключений...


AS>Ну и зачем это тогда тестировать?


Что бы определить скорость работы различных методов сообщения об ошибках. Фрейм исключений — это только часть.
Не понимаю, что тебе не понятно? Вот гляди пример, на коотором можно сравнивать, при этом фреймов исключений нет:

void f_ex(int i)
{
  ex2(i+1);
  ex3(i+2);
  ex4(i+3);
}

int f_rv(int i)
{
  if (!f_rv2(i+1)) return 0;
  if (!f_rv3(i+2)) return 0;
  if (!f_rv4(i+3)) return 0;
  return 1;
}




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


AS>>>В общем, надо моделировать _реальный_ код, а не пустые функции. А для этого надо иметь статистику по виду и функциональности AS>функций. У тебя таковая есть?


R>>Такая задача не ставилась, т.к. это будет очень серьёзное исследование. И имхо оно здесь не надо, т.к. я исследовал примитивы, вычислительную сложность можно просто сложить для получения результата.


AS> Понятно. Дальше можно не продолжать.


AS>>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга.

AS>>>
AS>>>Не был бы так однозначен. По крайней мере кол-во инструкций и время выполнения связаны не линейно.
R>>Тем более я, как инженер, больше верю своим глазам

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


AS>>>Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки


R>>Почему? Там не более 2-3 инструкций.


AS>Наивно... Ты посмотри, _какие_ там инструкции.


AS>>>(особенно с учетом работающего механизма предсказания переходов). Поэтому обычно и стараются вынести это за пределы цикла — тогда, если код _только_ вычислительный, или же "толстая" прослойка до финальной функции (где проверка и генерация исключения) получится выигрыш.


R>>Может быть ты приведёшь какие-то замеры Мои замеры пока показывают обратную картину....


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



AS>>>Не все так просто. Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора. В случае многозадачной системы это как минимум неверно.


R>>Не было никакой "многозадачной системы" и время я брал минимальное за много выполнений.

R>>Это время не менялось от запуска к запуску. Имхо ты говоришь что-то не то...

AS>Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.


Зачем привязывать к единственному ядру? Или ты боишься, что у меня часть вычислений убежало на соседний комп?
Зачем поднимать приоритеты? Или ты думаешь, что поток с более высоким приоритетом будет выполняться быстрее?


AS>>>Выложи исходники — я тебя уверяю, народ раскритикует по самые


R>>Код чего интересует?

R>>Сами тестируемые функции? Или что?

AS>Все — полный тест юнит.



Я не понимаю твой поинт имхо уже наполовину переходящий в наезды. Ты хочешь сказать, что либо я выдумал цифры, либо неправильно мерял?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:33
Оценка:
AS>>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга. Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки (особенно с учетом работающего механизма предсказания переходов).

СМ>>на вскидку — установка фрейма пара команд, ну мб три. снятие еще пара. и БЕЗ переходов. а вот проверка та же пара, но с переходом да и установка еще одна (в самой ф-ии). (это на I86). Итого 4(5) против 3.


AS>Установка фрейма. Вот типичный вариант (часть команд создания стек фрейма я включил сознательно, об этом ниже):


AS>
AS>    mov    ebp, esp
AS>    push    -1
AS>    push    $callback
AS>    mov    eax, DWORD PTR fs:__except_list
AS>    push    eax
AS>    mov    DWORD PTR fs:__except_list, esp
AS>


Да, совсем забыл — еще ж надо снять фрейм

    mov    ecx, DWORD PTR __$EHRec$[ebp+4]
    mov    DWORD PTR fs:__except_list, ecx
    mov    esp, ebp
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: [Investigation] Exceptions vs. Return Values
От: AndrewJD США  
Дата: 02.04.07 08:36
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

AS>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга.

ИМХО, совсем недостаточно. Ты точно знаешь какие команды могут процом паралельно выполнятся и как они влияют друг на друга?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[7]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:41
Оценка: -1
AS>>Ну и зачем это тогда тестировать?

R>Что бы определить скорость работы различных методов сообщения об ошибках. Фрейм исключений — это только часть.

R>Не понимаю, что тебе не понятно? Вот гляди пример, на коотором можно сравнивать, при этом фреймов исключений нет:

R>
R>void f_ex(int i)
R>{
R>  ex2(i+1);
R>  ex3(i+2);
R>  ex4(i+3);
R>}

R>int f_rv(int i)
R>{
R>  if (!f_rv2(i+1)) return 0;
R>  if (!f_rv3(i+2)) return 0;
R>  if (!f_rv4(i+3)) return 0;
R>  return 1;
R>}
R>


Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.

AS>>Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.


R>Зачем привязывать к единственному ядру? Или ты боишься, что у меня часть вычислений убежало на соседний комп?


Куда убежать??? Вероятно, про багу с рассинхронизаций rdtsc на разных ядрах ты не слышал?

R>Зачем поднимать приоритеты? Или ты думаешь, что поток с более высоким приоритетом будет выполняться быстрее?


Круто.

AS>>>>Выложи исходники — я тебя уверяю, народ раскритикует по самые


R>>>Код чего интересует?

R>>>Сами тестируемые функции? Или что?

AS>>Все — полный тест юнит.


R>Я не понимаю твой поинт имхо уже наполовину переходящий в наезды. Ты хочешь сказать, что либо я выдумал цифры, либо неправильно мерял?

Это не наезд, а критический анализ. То, что тебе он не нравится — уже означает его претензии на валидность Так чего тебе бояться — я не понимаю причин для того, чтобы не выложить полный проект. Если жалко трудов — так и скажи. Но только по результатам судить о тесте — уж извини. Это действительно инженерный подход, который для исследований не годится.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:45
Оценка:
AS>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга.
AJD>ИМХО, совсем недостаточно. Ты точно знаешь какие команды могут процом паралельно выполнятся и как они влияют друг на друга?

Достаточно для оценки ситуации и выводов о необходимости замеров. Мерить все подряд не понимая, что собственно измеряешь — смысл?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 08:47
Оценка:
AS>>Даже замеры времени по rdtsc — это неправильно (если уж придираться), поскольку учитывает не время потока, а все такты процессора.
CC>Увы, но более точного метода измерения кроме как
CC>
CC>    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
CC>    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
CC>

CC>и rdtsc пока ИМХО никто не предложил...

И еще не забывай про привязку к одному ядру. А вот что автор тестов ответил на все это — можешь прочитать сам
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: AndrewJD США  
Дата: 02.04.07 09:03
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Достаточно для оценки ситуации и выводов о необходимости замеров.

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

AS>Мерить все подряд не понимая, что собственно измеряешь — смысл?

Это да.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 09:05
Оценка:
То, что исключения позволяют сократить один if при вызове функции, по-моему, с лихвой компенсируется тем, что исключения вынуждают пользоваться обертками в виде умных указателей.
Re[7]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 09:11
Оценка:
AS>>Достаточно для оценки ситуации и выводов о необходимости замеров.
AJD>Если код отличается на несколко инстукций, тяжело что-то сказать прое его скорость в общем случае.

В данном случае разница довольно существенна. К тому же я не призываю отказаться от измерений — а лишь понимать, что именно измеряется. А не просто анализировать статистику.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 09:14
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>И еще не забывай про привязку к одному ядру. А вот что автор тестов ответил на все это — можешь прочитать сам

Да, совсем забыл:
    SetProcessAffinityMask (GetCurrentProcess (),1);
    // и для гарантии контрольный в голову!!!
    SetThreadAffinityMask (GetCurrentThread (),1);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 09:14
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Куда убежать??? Вероятно, про багу с рассинхронизаций rdtsc на разных ядрах ты не слышал?

Кстати интел утверждает что "ссинхронизировать" tsc разных ядер можно путем вызова QueryPerormanceCounter.
Правда как именно они это делают я так и не понял. А трасить QueryPerormanceCounter уж очень неохота...
Хотя результаты моих тестов как на HT (P630) так и на дуалах (P915) расхождения в чистых rdtsc не выявили.
Впрочем лучше уж будем и дальше перестраховываться...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 09:14
Оценка:
Здравствуйте, remark, Вы писали:

R>Зачем привязывать к единственному ядру?

Затем, что ОС по своей прихоти может перебросить поток на другое ядро. С учетом таких забавных современных заморочек как динамическое управление частотой проца у разных ядер может оказаться разная частота — соответственно разное значение tsc. Дошло?

R>Зачем поднимать приоритеты?

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

AS>>>>Выложи исходники

Да, исходники в студию. Потому как мне например руки чешутся посмотреть на результаты их работы из под ICC
Заодно доработаем их всей толпой до полноценного теста...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [Investigation] Exceptions vs. Return Values
От: StevenIvanov США  
Дата: 02.04.07 09:20
Оценка:
Здравствуйте, minorlogic, Вы писали:

M> ...


M>6. Очень интересен анал хотя бы под одну embeded платформу.


Для ARM-платформ все далеко не так радужно. Если привязываться к коду использующему исключения генерируемому gcc для ARM, то там имеют место быть так называемые stack unwind tables — для каждой функции генерируется такое безобразие. Размер кода увеличивается довольно серъезно. По своему опыту помню, как после перекомпиляции с ключом -fexceptions 300 килобайтная программа стала весить 450. Довольно серъезный недостаток для embedded devices.
Как обыкновение под embedded платформы используют два ключа компиляции: -fno-exceptions и -fno-rtti(правда поддержка rtti обходится сравнительно небольшим довеском к коду).
Причина по которой gcc генерирует столь медленный код для win32 думается связана с тем, что gcc использует общую схему обработки исключений, который в общих чертах независим от платформы. Win32 SEH не используется gcc.
Re: [Investigation] Exceptions vs. Return Values
От: rm822 Россия  
Дата: 02.04.07 10:02
Оценка: +1 -1
Здравствуйте, remark

Вам не стыдно?
Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?
Не указана потоковоя модель ST\MT и способ линковки рантайма lib\dll
Какой класс исключения вы использовали? (Я надеюсь он был производным от std::runtime_error? или вы bool кидали? )
Как насчет полиморфного поведения?
Как насчет ловли ссылок на один из базовых классов в иерархии?
Как насчет ловли ссылок на один из производных классов в иерархии?

Двойка вам за научный подход.

R>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:35
Оценка:
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, remark


R>Вам не стыдно?

R>Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?

Возможно стыд мне и позор, но первый раз про такое слышу. Или слышал под другим названием.
Что за синхроннная/асинхронная модель?

R>Не указана потоковоя модель ST\MT и способ линковки рантайма lib\dll


Это никак не повлияет, поэтому и не указывал. Там нет вызовов из рантайма. Возможно за исключением кидания исключения, но там небольшой оверхед на синхронизацию никак не скажется.

R>Какой класс исключения вы использовали? (Я надеюсь он был производным от std::runtime_error? или вы bool кидали? )


int
Я думаю это тоже неважно, за исключением небольшого оверхеда при кидании.

R>Как насчет полиморфного поведения?


А что насчёт него?

R>Как насчет ловли ссылок на один из базовых классов в иерархии?


А что насчёт него?

R>Как насчет ловли ссылок на один из производных классов в иерархии?


А что насчёт него?


R>Двойка вам за научный подход.


R>>

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>То, что исключения позволяют сократить один if при вызове функции, по-моему, с лихвой компенсируется тем, что исключения вынуждают пользоваться обертками в виде умных указателей.


Умные указатели подпадают под категорию того, что я называл "ресурсами", т.е. объектами с нетривиальным деструктором. Никак это не компенсируется.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 10:39
Оценка:
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, remark


R>Вам не стыдно?

R>Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?

R>Не указана потоковоя модель ST\MT и способ линковки рантайма lib\dll


при чем здесь это?

R>Какой класс исключения вы использовали? (Я надеюсь он был производным от std::runtime_error? или вы bool кидали? )

R>Как насчет полиморфного поведения?
R>Как насчет ловли ссылок на один из базовых классов в иерархии?
R>Как насчет ловли ссылок на один из производных классов в иерархии?

R>Двойка вам за научный подход.


R>>
Re[3]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:40
Оценка: +1
Здравствуйте, StevenIvanov, Вы писали:

SI>Здравствуйте, minorlogic, Вы писали:


M>> ...


M>>6. Очень интересен анал хотя бы под одну embeded платформу.


SI>Для ARM-платформ все далеко не так радужно. Если привязываться к коду использующему исключения генерируемому gcc для ARM, то там имеют место быть так называемые stack unwind tables — для каждой функции генерируется такое безобразие. Размер кода увеличивается довольно серъезно. По своему опыту помню, как после перекомпиляции с ключом -fexceptions 300 килобайтная программа стала весить 450. Довольно серъезный недостаток для embedded devices.


Это сравнение теплого и мягкого. Надо не просто перекомпилировать программу с исключениями или без. Т.к. сообщение об ошибках с помощью возвращаемых значений могут раздуть код до 3 раз. Сравни:
call f


и:

call f
test eax, eax
je ...



Вопрос: какая программа будет меньше, использующая исключения и скомпилированная с исключениями или неиспользующая исключения и скомпилированная без исключений.
А то, что программа написанная без исключений, но скомпилированная с исключениями будет больше программы написанной без исключений, и скомпилированной без исключениями — это понятно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 10:43
Оценка:
В дополнение к сказанному.
Этот сэкономленный if играет роль только когда тело функции пустое. Если функция хоть что-то делает, тем более в цикле, то такая экономия не играет никакой роли. Так что эксперимент поставлен абсолютно некорректно.

Олег Алексеев.
Re[3]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 10:45
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, rm822, Вы писали:


R>>Здравствуйте, remark


R>>Вам не стыдно?

R>>Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?

R>Возможно стыд мне и позор, но первый раз про такое слышу. Или слышал под другим названием.

R>Что за синхроннная/асинхронная модель?

это vc specific:

/EHa
/EHsc

[]
Re[7]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:45
Оценка: 1 (1)
Здравствуйте, Andrew S, Вы писали:

AS>>>>А вообще, и замерять то особо ничего не надо — достаточно анализа ассемблерного листинга. Установка фрейма исключений в цикле — довольно дорогая операция, значительно дороже, чем проверка ошибки (особенно с учетом работающего механизма предсказания переходов).


СМ>>>на вскидку — установка фрейма пара команд, ну мб три. снятие еще пара. и БЕЗ переходов. а вот проверка та же пара, но с переходом да и установка еще одна (в самой ф-ии). (это на I86). Итого 4(5) против 3.


AS>>Установка фрейма. Вот типичный вариант (часть команд создания стек фрейма я включил сознательно, об этом ниже):


AS>>
AS>>    mov    ebp, esp
AS>>    push    -1
AS>>    push    $callback
AS>>    mov    eax, DWORD PTR fs:__except_list
AS>>    push    eax
AS>>    mov    DWORD PTR fs:__except_list, esp
AS>>


AS>Да, совсем забыл — еще ж надо снять фрейм


AS>
AS>    mov    ecx, DWORD PTR __$EHRec$[ebp+4]
AS>    mov    DWORD PTR fs:__except_list, ecx
AS>    mov    esp, ebp
AS>



Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.
Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.
при использовании возвращаемых значнеий — нет пролога/эпилога, зато каждый вызов функции/выделение ресурса обходится дороже.
Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.

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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:47
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, Andrew S, Вы писали:


AS>>И еще не забывай про привязку к одному ядру. А вот что автор тестов ответил на все это — можешь прочитать сам

CC>Да, совсем забыл:
CC>
CC>    SetProcessAffinityMask (GetCurrentProcess (),1);
CC>    // и для гарантии контрольный в голову!!!
CC>    SetThreadAffinityMask (GetCurrentThread (),1);
CC>


О чём вы вообще говорите?! Ну не может код выполняться на разных процессорах/ядрах, если всего один процессор и одно ядро!
И не может так быть, что бы кусок кода, выполняемый 24 такта 1000 раз подряд, каждый из этих 1000 раз прерывался таймером.
Я не понимаю, о чём вы говорите.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 10:56
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.


Ну хорошо, а ты что утверждаешь, что реальный код — это только код с трансляцией исключений?
Я надеюсь, что нет. Тогда почему не начать с простого случая?
Я тебя уверяю, что есть множество кода, который никакими трансляциями не занимается.


AS>>>Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.


R>>Зачем привязывать к единственному ядру? Или ты боишься, что у меня часть вычислений убежало на соседний комп?


AS>Куда убежать??? Вероятно, про багу с рассинхронизаций rdtsc на разных ядрах ты не слышал?


Нет, чтобы на одном ядре таймер сам с собой рассинхронизировался, я не слышал. А что такое бывает?


R>>Зачем поднимать приоритеты? Или ты думаешь, что поток с более высоким приоритетом будет выполняться быстрее?


AS> Круто.


Вот я тоже так подумал.

AS>>>>>Выложи исходники — я тебя уверяю, народ раскритикует по самые


R>>>>Код чего интересует?

R>>>>Сами тестируемые функции? Или что?

AS>>>Все — полный тест юнит.


R>>Я не понимаю твой поинт имхо уже наполовину переходящий в наезды. Ты хочешь сказать, что либо я выдумал цифры, либо неправильно мерял?

AS>Это не наезд, а критический анализ. То, что тебе он не нравится — уже означает его претензии на валидность Так чего тебе бояться — я не понимаю причин для того, чтобы не выложить полный проект. Если жалко трудов — так и скажи. Но только по результатам судить о тесте — уж извини. Это действительно инженерный подход, который для исследований не годится.

Мне не жалко трудов, просто проект получился достаточно наколеночный, т.к. когда я начинал, то не собирался делать что-то особо основательное. Но если ты так настаиваешь, сейчас всё это запакую и выложу.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [Investigation] Exceptions vs. Return Values
От: rm822 Россия  
Дата: 02.04.07 11:03
Оценка: :)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, rm822, Вы писали:


R>>Здравствуйте, remark


R>>Вам не стыдно?

R>>Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?

R>Возможно стыд мне и позор, но первый раз про такое слышу. Или слышал под другим названием.

R>Что за синхроннная/асинхронная модель?
http://msdn2.microsoft.com/en-us/library/1deeycx5.aspx

R>>Не указана потоковоя модель ST\MT и способ линковки рантайма lib\dll


R>Это никак не повлияет, поэтому и не указывал. Там нет вызовов из рантайма. Возможно за исключением кидания исключения, но там небольшой оверхед на синхронизацию никак не скажется.

Вы проверяли? Если нет то вы не знаете, это только догадки, а разработчики как известно не могут с достаточной достоверностью предсказывать узкие места.

R>>Какой класс исключения вы использовали? (Я надеюсь он был производным от std::runtime_error? или вы bool кидали? )


R>int


R>Я думаю это тоже неважно, за исключением небольшого оверхеда при кидании.
Вы думаете, но вы не знаете. Это важно. Дополнительный new\delete + вступают в силу заморочки с полиморфным поведением.
То что кто-то будет кидать Int крайне маловероятно, а здравый смысл требует гомоморфную иерархию классов исключений. std использует в качестве базы std::exception. Даже если вы хотите использовать какой-то свой класс как пращура, то все равно он должен быть наследником std::exception

R>>Как насчет полиморфного поведения?

R>А что насчёт него?
сколько займет вызов виртуального деструктора?

R>>Как насчет ловли ссылок на один из базовых классов в иерархии?

R>А что насчёт него?
try{
throw std::runtime_error("")
} catch(std::exception&) //сколько займет проверка того что std::runtime_error наследник std::exception?
{}

R>>Как насчет ловли ссылок на один из производных классов в иерархии?

R>А что насчёт него?
try{
throw std::exception("")
} catch(std::runtime_error&) //сколько займет проверка того что здесь catch не сработает?
{}


вполне реальная ситуация
try{
...
}
catch(SqlException& e) {....}
catch(IOException& e) {....}
catch(std::exception& e) { что-то не срослось }


R>>Двойка вам за научный подход.


R>>>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 11:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В дополнение к сказанному.

А>Этот сэкономленный if играет роль только когда тело функции пустое. Если функция хоть что-то делает, тем более в цикле, то такая экономия не играет никакой роли. Так что эксперимент поставлен абсолютно некорректно.

Ты сам себе противоречишь — вначале говоришь, что надо, что б функция что-то делала, а потом, говоришь, что тогда все результаты будут не видны.
Имхо я как раз всё сделал как надо — меряю вклад тогда, когда он виден. А не наоборот.

А>Олег Алексеев.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 11:09
Оценка:
Здравствуйте, rm822, Вы писали:

[]

R>>>Какой класс исключения вы использовали? (Я надеюсь он был производным от std::runtime_error? или вы bool кидали? )


R>>int

R>
R>>Я думаю это тоже неважно, за исключением небольшого оверхеда при кидании.
R>Вы думаете, но вы не знаете. Это важно. Дополнительный new\delete + вступают в силу заморочки с полиморфным поведением.
R>То что кто-то будет кидать Int крайне маловероятно, а здравый смысл требует гомоморфную иерархию классов исключений. std использует в качестве базы std::exception. Даже если вы хотите использовать какой-то свой класс как пращура, то все равно он должен быть наследником std::exception

ничего он не должен. Это рекомендация

R>>>Как насчет полиморфного поведения?

R>>А что насчёт него?
R>сколько займет вызов виртуального деструктора?

кто кидает указатели? Нафиг это надо?

R>>>Как насчет ловли ссылок на один из базовых классов в иерархии?

R>>А что насчёт него?
R>try{
R> throw std::runtime_error("")
R>} catch(std::exception&) //сколько займет проверка того что std::runtime_error наследник std::exception?
R>{}

хз, думаю, недолго

R>>>Как насчет ловли ссылок на один из производных классов в иерархии?

R>>А что насчёт него?
R>try{
R> throw std::exception("")
R>} catch(std::runtime_error&) //сколько займет проверка того что здесь catch не сработает?
R>{}

the same

R>вполне реальная ситуация

R>try{
R> ...
R>}
R>catch(SqlException& e) {....}
R>catch(IOException& e) {....}
R>catch(std::exception& e) { что-то не срослось }


R>>>Двойка вам за научный подход.


R>>>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 11:11
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, remark, Вы писали:


R>>Здравствуйте, rm822, Вы писали:


R>>>Здравствуйте, remark


R>>>Вам не стыдно?

R>>>Вы не упоямянули какую модель обработки исключений использовали, синхронную или асинхронную. Вы же не будете утверждать что между ними нет никакой существенной разницы?

R>>Возможно стыд мне и позор, но первый раз про такое слышу. Или слышал под другим названием.

R>>Что за синхроннная/асинхронная модель?

КЛ>это vc specific:


КЛ>/EHa

КЛ>/EHsc

КЛ>[]


Аааа. Понял о чём речь.
Ну вы же видите результаты, когда исключение кидается — всякие вариации, типа синхронной/асинхронной модели или кидать int или runtime_error, версия рантайма — это уже как мёртвому припарка — кидание исключений СУЩЕСТВЕННО НА МНОГО более медленные. Я не думаю, что из-за настроек время станет вдруг не 20мкс, а 10нс.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 11:15
Оценка:
Здравствуйте, remark, Вы писали:

R>О чём вы вообще говорите?! Ну не может код выполняться на разных процессорах/ядрах, если всего один процессор и одно ядро!У

У меня например 1 проц — 2 ядра... При особом желании могу нарыть как 2 процессорную так и четырехядерную машины... На них еще как может.
Речь тут о правильной методике тестирования. Разумеется если у тебя однояйцевый проц, то тогда тебе не надо париться касательно ядер. Но для правильного результата надо учитывать нюансы исполнения кода как на 1 так и на 2+ ядерниках.

R>И не может так быть, что бы кусок кода, выполняемый 24 такта 1000 раз подряд, каждый из этих 1000 раз прерывался таймером.

Колво циклов надо увеличить по любому — слишком мало — будет сказываться погрешность измерений.

R>

разумеется
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 11:24
Оценка:
Здравствуйте, rm822, Вы писали:

R>>>Двойка вам за научный подход.


Тут основная проблема, что бы сделать тесты справедливые для обоих стратегий.
Т.е. что я делаю — беру некую предельно простую абстракцию — ресурс — приписываю ему семантику — его надо выделить, причём выделение может провалится, и его обязательно надо освободить при выходе из функции. Далее я моделирую эту абстракцию на С++ и на С предельно "честно" по отношению к обоим языкам и их возможностям — на С++ — объект с деструктором, на С — функции construct/destroy. И сравниваю именно эти реализации одной и той же задачи разными средствами. Какая реализация быстрее?
Сравнивать тёплое с мягким нет смысла.
Т.е. нет смысла мерить типа "а что если мы в с++ вставим дополнительный new/delete" — ты тогда и в С вставь тоже что-то, что будет решать ту задачу, для решения которой ты в С++ вставил дополнительный new/delete.
Т.е. ты придумай некую абстрактную задачу, которая бы на С++ требовала применения иерархий ошибок/динамического полиморфизма и т.д., потом максимально "честно" вырази её решение на С, причём там, что бы тебе потом не говорили — а я бы это сделал подругому и быстрее. И вот тогда будем мерить, где решение задачи "мега динамической полиморфной обработки ошибок" работает быстрее.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 11:30
Оценка:
Здравствуйте, remark, Вы писали:

R>Ты сам себе противоречишь — вначале говоришь, что надо, что б функция что-то делала, а потом, говоришь, что тогда все результаты будут не видны.

R>Имхо я как раз всё сделал как надо — меряю вклад тогда, когда он виден. А не наоборот.

Я хочу сказать, что практическая ценность этого измерения незначительна. Мы же на практике не пишем пустых функций.

Ещё я боюсь, что сейчас появится куча людей, утверждающих, что преимущество исключений доказано экспериментально, но забывающих указать в каких условиях оно проявляется. Между тем, написать exception-safe программу ох как непросто.

Олег Алексеев.

Re[9]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 11:32
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, remark, Вы писали:


R>>О чём вы вообще говорите?! Ну не может код выполняться на разных процессорах/ядрах, если всего один процессор и одно ядро!У

CC>У меня например 1 проц — 2 ядра... При особом желании могу нарыть как 2 процессорную так и четырехядерную машины... На них еще как может.

Либо я чего-то не понимаю...
То, что ты можешь нарыть 2 процессорную тачку никак не сказывается на том, будет ли у меня погрешность измерений, если я на одноядерной тачке не привяжу потоки к ядрам.
На одноядерной тачке не надо ничего привязывать. Я учёл все ньюансы, адекватные в конкретной ситуации. Если бы я запускал на многоядерной такчке, тогда бы я парился по поводу привязки и т.д.
Я не понимаю о чём речь. Почему Andrew S говорит, что я забыл сделать какую-то привязку, поднять приоритеты и т.д. Слов просто нет.
Не знаю даже, что вам ещё сказать. Или если вы тут о чём-то своём говорите, типа "как мы будем мерить производительность на многоядерной тачке", то то не говорите, что я что-то забыл.


R>>И не может так быть, что бы кусок кода, выполняемый 24 такта 1000 раз подряд, каждый из этих 1000 раз прерывался таймером.

CC>Колво циклов надо увеличить по любому — слишком мало — будет сказываться погрешность измерений.

Именно поэтому потом я делал замеры в "асимптотическом" случае.

R>>

CC>разумеется

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 11:50
Оценка:
Здравствуйте, remark, Вы писали:

[]

R>Я не понимаю о чём речь. Почему Andrew S говорит, что я забыл сделать какую-то привязку, поднять приоритеты и т.д. Слов просто нет.

R>Не знаю даже, что вам ещё сказать. Или если вы тут о чём-то своём говорите, типа "как мы будем мерить производительность на многоядерной тачке", то то не говорите, что я что-то забыл.

ну это он для надежности. Вдруг какой-либо другой поток вклинится в подсчитанные такты.

[]
Re[5]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 11:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, remark, Вы писали:


R>>Ты сам себе противоречишь — вначале говоришь, что надо, что б функция что-то делала, а потом, говоришь, что тогда все результаты будут не видны.

R>>Имхо я как раз всё сделал как надо — меряю вклад тогда, когда он виден. А не наоборот.

А>Я хочу сказать, что практическая ценность этого измерения незначительна. Мы же на практике не пишем пустых функций.


А>Ещё я боюсь, что сейчас появится куча людей, утверждающих, что преимущество исключений доказано экспериментально, но забывающих указать в каких условиях оно проявляется. Между тем, написать exception-safe программу ох как непросто.


конечно, поэтому давайте писать простые совсем не exception-safe программы .

Его поинт в том, что сама по себе поддержка исключений вносит практически нулевой оверхэд.

А>Олег Алексеев.


А>
Re[8]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 11:54
Оценка:
R>Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.

Я хочу сказать, что там не 2-3 команды, а десяток довольно толстых как сточки зрения кода, так и данных, команд.

R>Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.

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

R>Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.


Чушь. Твоя запись if (!fun()) return val как раз не общий случай. Его я могу оптимизировать до одной проверки на все функции. val1 = fun1() ... valn = funn(); return val1 | val2 | ... | valn. В принципе, это может сделать и сам компилятор (более того, он это хоть и коряво, на пытается при помощи setne сделать). И что это покажет? Я говорю — нужны реальные паттерны.

R>з.ы. кстати, если в функции нет объектов с нетривиальными деструкторами, то исключения выглядят значительно привлекательнее, т.к. и эпилога/пролога нет и вызовы функции дешевле.


Не вышлядят. Блин, ну сколько можно — я ж уже показал, что в этом случае используется ebp стек фрейм. Попробуй лучше исследовать, как это влияет на перфоманс вычислительной функции, а?

Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: [Investigation] Exceptions vs. Return Values
От: rm822 Россия  
Дата: 02.04.07 11:55
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, rm822, Вы писали:


R>>>>Двойка вам за научный подход.


R>Тут основная проблема, что бы сделать тесты справедливые для обоих стратегий.

R>Т.е. что я делаю — беру некую предельно простую абстракцию — ресурс — приписываю ему семантику — его надо выделить, причём выделение может провалится, и его обязательно надо освободить при выходе из функции. Далее я моделирую эту абстракцию на С++ и на С предельно "честно" по отношению к обоим языкам и их возможностям — на С++ — объект с деструктором, на С — функции construct/destroy. И сравниваю именно эти реализации одной и той же задачи разными средствами. Какая реализация быстрее?
R>Сравнивать тёплое с мягким нет смысла.
R>Т.е. нет смысла мерить типа "а что если мы в с++ вставим дополнительный new/delete" — ты тогда и в С вставь тоже что-то, что будет решать ту задачу, для решения которой ты в С++ вставил дополнительный new/delete.
R>Т.е. ты придумай некую абстрактную задачу, которая бы на С++ требовала применения иерархий ошибок/динамического полиморфизма и т.д., потом максимально "честно" вырази её решение на С, причём там, что бы тебе потом не говорили — а я бы это сделал подругому и быстрее. И вот тогда будем мерить, где решение задачи "мега динамической полиморфной обработки ошибок" работает быстрее.

Реальность такова что для обработки исключений используется иерахия классов а не int.(Обычно) Для обработки ошибок error-кодами используется int а не классы. (Обычно) И сравнивать нужно именно теплое с мягким, потому что такова реальность.

R>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[11]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 12:00
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, remark, Вы писали:


КЛ>[]


R>>Я не понимаю о чём речь. Почему Andrew S говорит, что я забыл сделать какую-то привязку, поднять приоритеты и т.д. Слов просто нет.

R>>Не знаю даже, что вам ещё сказать. Или если вы тут о чём-то своём говорите, типа "как мы будем мерить производительность на многоядерной тачке", то то не говорите, что я что-то забыл.

КЛ>ну это он для надежности. Вдруг какой-либо другой поток вклинится в подсчитанные такты.


Во-первых, thread affinity тут всё равно ни при чём
Во-вторых, от "вклинивания" на win32/linux всё равно никак не защититься

КЛ>[]

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 12:01
Оценка:
AS>>Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.

R>Ну хорошо, а ты что утверждаешь, что реальный код — это только код с трансляцией исключений?

R>Я надеюсь, что нет. Тогда почему не начать с простого случая?
R>Я тебя уверяю, что есть множество кода, который никакими трансляциями не занимается.

А я тебя уверяю в обратном. Сравни std и com исключения. Обычно в проекте своя иерархия исключений, и они транслируются на разных уровнях вызова. Как в этом случае добиться преймущества от исключений на уровне вызова библиотечных методов\функций — вопрос интересный.

AS>>>>Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.


R>>>Зачем привязывать к единственному ядру? Или ты боишься, что у меня часть вычислений убежало на соседний комп?


AS>>Куда убежать??? Вероятно, про багу с рассинхронизаций rdtsc на разных ядрах ты не слышал?


R>Нет, чтобы на одном ядре таймер сам с собой рассинхронизировался, я не слышал. А что такое бывает?


А при чем тут один. Ты тестировал на одной конфигурации?

R>>>Зачем поднимать приоритеты? Или ты думаешь, что поток с более высоким приоритетом будет выполняться быстрее?


AS>> Круто.


R>Вот я тоже так подумал.


Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?

R>Мне не жалко трудов, просто проект получился достаточно наколеночный, т.к. когда я начинал, то не собирался делать что-то особо основательное. Но если ты так настаиваешь, сейчас всё это запакую и выложу.


Да нет, я не настаиваю. Просто если ты хочешь называть это исследованием и чтобы его результаты имели практическую ценность и обоснованность — должен быть виден код, который приводит к таким результатам. Скажи честно, ты смотрел для каждого варианта то, что генерит компилятор на уровне ассемблера? Ты разбирался как каждый из них работает с исключениями и с возвращающими значениями и влияние этого на кодогенерацию в целом? А ведь это все нужно, чтобы не просто статистику поиметь, а сделать из нее выводы — самое ценное, что есть в исследовании. Я выводов пока (как и самого исследования) пока тут не вижу, уж извини.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 12:04
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Его поинт в том, что сама по себе поддержка исключений вносит практически нулевой оверхэд.


Если бы более точным, то я хочу померить оверхед обработки ошибок отдельно Допустим получается 100нс/1000 строк кода при использовании кодов возврата и 95нс/1000 строк кода.
Дальше каждый сам волен решать — важно ему это или нет. Важно ли ему эти 5 нс.
Но утвержать, что это просто не важно, имхо, некорректно.

А>>Олег Алексеев.


А>>

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: [Investigation] Exceptions vs. Return Values
От: Константин Л. Франция  
Дата: 02.04.07 12:05
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.


R>>Ну хорошо, а ты что утверждаешь, что реальный код — это только код с трансляцией исключений?

R>>Я надеюсь, что нет. Тогда почему не начать с простого случая?
R>>Я тебя уверяю, что есть множество кода, который никакими трансляциями не занимается.

AS>А я тебя уверяю в обратном. Сравни std и com исключения. Обычно в проекте своя иерархия исключений, и они транслируются на разных уровнях вызова. Как в этом случае добиться преймущества от исключений на уровне вызова библиотечных методов\функций — вопрос интересный.


com исключения? это что?
Re[6]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 12:06
Оценка:
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, remark, Вы писали:


R>>Здравствуйте, rm822, Вы писали:


R>>>>>Двойка вам за научный подход.


R>>Тут основная проблема, что бы сделать тесты справедливые для обоих стратегий.

R>>Т.е. что я делаю — беру некую предельно простую абстракцию — ресурс — приписываю ему семантику — его надо выделить, причём выделение может провалится, и его обязательно надо освободить при выходе из функции. Далее я моделирую эту абстракцию на С++ и на С предельно "честно" по отношению к обоим языкам и их возможностям — на С++ — объект с деструктором, на С — функции construct/destroy. И сравниваю именно эти реализации одной и той же задачи разными средствами. Какая реализация быстрее?
R>>Сравнивать тёплое с мягким нет смысла.
R>>Т.е. нет смысла мерить типа "а что если мы в с++ вставим дополнительный new/delete" — ты тогда и в С вставь тоже что-то, что будет решать ту задачу, для решения которой ты в С++ вставил дополнительный new/delete.
R>>Т.е. ты придумай некую абстрактную задачу, которая бы на С++ требовала применения иерархий ошибок/динамического полиморфизма и т.д., потом максимально "честно" вырази её решение на С, причём там, что бы тебе потом не говорили — а я бы это сделал подругому и быстрее. И вот тогда будем мерить, где решение задачи "мега динамической полиморфной обработки ошибок" работает быстрее.

R>Реальность такова что для обработки исключений используется иерахия классов а не int.(Обычно) Для обработки ошибок error-кодами используется int а не классы. (Обычно) И сравнивать нужно именно теплое с мягким, потому что такова реальность.


Обычно и не думают о наносекундах, и что?

R>>

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 12:07
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Его поинт в том, что сама по себе поддержка исключений вносит практически нулевой оверхэд.


В чём его поинт, автор уже написал:

>> Цель можно охарактеризовать примерно так: исследовать скорость работы некоторых ключевых паттернов кода, реализованных с применением исключений для сообщения об ошибках, или с помощью возвращаемых значений.


Написание пустых функций не есть "ключевой паттерн кода" (по-моему).

Нулевой оверхэд видел своими глазами (правда только у GCC). Назвать его нулевым по объему дополнительного кода язык не поворачивается. Поверьте, я не ратую за отмену исключений. Я за трезвую оценку и объективные исследования. Думаю, что критические отзывы пойдут только на пользу исследованиям.

Олег Алексеев.
Re[9]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 12:12
Оценка: -1
Здравствуйте, Andrew S, Вы писали:

R>>Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.


AS>Я хочу сказать, что там не 2-3 команды, а десяток довольно толстых как сточки зрения кода, так и данных, команд.


R>>Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.

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

R>>Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.


AS>Чушь. Твоя запись if (!fun()) return val как раз не общий случай. Его я могу оптимизировать до одной проверки на все функции. val1 = fun1() ... valn = funn(); return val1 | val2 | ... | valn. В принципе, это может сделать и сам компилятор (более того, он это хоть и коряво, на пытается при помощи setne сделать). И что это покажет? Я говорю — нужны реальные паттерны.


Это не оптимизация общего случая — пример — вложенные ресурсы.

Ну допустим, я бы потратил пол-года и переписал некий проект bla-bla с одной стратегии на другую и выдал бы в итоге, что с исключениями bla-bla стал работать на 1% быстрее и размер уменьшился на 2%. Ну и что? По-твоему это бы дало больше информации?
Мы же не штампуем целиком проекты, мы пишем отдельные функции — вот тут функци, которая форвардит вызов другой, а вот тут функция, которая вызывает ещё 3 функции, а вот тут функция, которая выделяет ресурс и т.д.


R>>з.ы. кстати, если в функции нет объектов с нетривиальными деструкторами, то исключения выглядят значительно привлекательнее, т.к. и эпилога/пролога нет и вызовы функции дешевле.


AS>Не вышлядят. Блин, ну сколько можно — я ж уже показал, что в этом случае используется ebp стек фрейм. Попробуй лучше исследовать, как это влияет на перфоманс вычислительной функции, а?


А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.

AS>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


Так же как и возвращаемые значения. Очевидно. Осталось только понять как.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: [Investigation] Exceptions vs. Return Values
От: Sergey Россия  
Дата: 02.04.07 12:19
Оценка:
Здравствуйте, remark, Вы писали:

R>Аааа. Понял о чём речь.

R>Ну вы же видите результаты, когда исключение кидается — всякие вариации, типа синхронной/асинхронной модели или кидать int или runtime_error, версия рантайма — это уже как мёртвому припарка — кидание исключений СУЩЕСТВЕННО НА МНОГО более медленные. Я не думаю, что из-за настроек время станет вдруг не 20мкс, а 10нс.

Не совсем так. Асинхронная можель обработки исключений в VC (название неудачное, но так уж назвали) означает, что исключение может кинуть любая функция, в том числе сишная. Плюс SEH-исключения будут ловиться по catch(..). Т.е., компилятор просто будет втыкать код для размотки стека в большем количестве случаев. Соответственно, повлияет это и на нормальное исполнение программы, когда исключения не кидаются.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[11]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 12:23
Оценка:
AS>>>>Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.

R>>>Ну хорошо, а ты что утверждаешь, что реальный код — это только код с трансляцией исключений?

R>>>Я надеюсь, что нет. Тогда почему не начать с простого случая?
R>>>Я тебя уверяю, что есть множество кода, который никакими трансляциями не занимается.

AS>>А я тебя уверяю в обратном. Сравни std и com исключения. Обычно в проекте своя иерархия исключений, и они транслируются на разных уровнях вызова. Как в этом случае добиться преймущества от исключений на уровне вызова библиотечных методов\функций — вопрос интересный.


КЛ>com исключения? это что?


Например, COleException. В этом случае мы имеем дело аж с 2-мя враппингами — перевод возвращаемого значения в ole иключение, перевод ole исключения в наше родное. И это все вполне common случай. Я ж говорю — различные библиотечные методы\функции.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: Sergey Россия  
Дата: 02.04.07 12:24
Оценка: 2 (2) +1 :)
Здравствуйте, rm822, Вы писали:

R>>Тут основная проблема, что бы сделать тесты справедливые для обоих стратегий.

R>>Т.е. что я делаю — беру некую предельно простую абстракцию — ресурс — приписываю ему семантику — его надо выделить, причём выделение может провалится, и его обязательно надо освободить при выходе из функции. Далее я моделирую эту абстракцию на С++ и на С предельно "честно" по отношению к обоим языкам и их возможностям — на С++ — объект с деструктором, на С — функции construct/destroy. И сравниваю именно эти реализации одной и той же задачи разными средствами. Какая реализация быстрее?
R>>Сравнивать тёплое с мягким нет смысла.
R>>Т.е. нет смысла мерить типа "а что если мы в с++ вставим дополнительный new/delete" — ты тогда и в С вставь тоже что-то, что будет решать ту задачу, для решения которой ты в С++ вставил дополнительный new/delete.
R>>Т.е. ты придумай некую абстрактную задачу, которая бы на С++ требовала применения иерархий ошибок/динамического полиморфизма и т.д., потом максимально "честно" вырази её решение на С, причём там, что бы тебе потом не говорили — а я бы это сделал подругому и быстрее. И вот тогда будем мерить, где решение задачи "мега динамической полиморфной обработки ошибок" работает быстрее.

R>Реальность такова что для обработки исключений используется иерахия классов а не int.(Обычно) Для обработки ошибок error-кодами используется int а не классы. (Обычно) И сравнивать нужно именно теплое с мягким, потому что такова реальность.


Осталось еще добавить, что при обработке ошибок error-кодами (обычно) как минимум в половине случаев забывают проверять код возврата или не знают что с ним делать, и поэтому программа с обработкой ошибок error-кодами все равно будет быстрее Зато с исключениями — правильнее
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[10]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 12:26
Оценка: 1 (1)
Здравствуйте, Andrew S, Вы писали:

AS>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?


Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.

AS>Да нет, я не настаиваю. Просто если ты хочешь называть это исследованием и чтобы его результаты имели практическую ценность и обоснованность — должен быть виден код, который приводит к таким результатам. Скажи честно, ты смотрел для каждого варианта то, что генерит компилятор на уровне ассемблера? Ты разбирался как каждый из них работает с исключениями и с возвращающими значениями и влияние этого на кодогенерацию в целом? А ведь это все нужно, чтобы не просто статистику поиметь, а сделать из нее выводы — самое ценное, что есть в исследовании. Я выводов пока (как и самого исследования) пока тут не вижу, уж извини.


То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 12:30
Оценка:
R>>>Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.

AS>>Я хочу сказать, что там не 2-3 команды, а десяток довольно толстых как сточки зрения кода, так и данных, команд.


R>>>Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.

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

R>>>Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.


AS>>Чушь. Твоя запись if (!fun()) return val как раз не общий случай. Его я могу оптимизировать до одной проверки на все функции. val1 = fun1() ... valn = funn(); return val1 | val2 | ... | valn. В принципе, это может сделать и сам компилятор (более того, он это хоть и коряво, на пытается при помощи setne сделать). И что это покажет? Я говорю — нужны реальные паттерны.


R>Это не оптимизация общего случая — пример — вложенные ресурсы.


Это оптимизация приведенного тобой примера, в которой переход не требуется вообще...

R>Ну допустим, я бы потратил пол-года и переписал некий проект bla-bla с одной стратегии на другую и выдал бы в итоге, что с исключениями bla-bla стал работать на 1% быстрее и размер уменьшился на 2%. Ну и что? По-твоему это бы дало больше информации?


Не проект. Надо выделить несколько функций различных классов, и уже на их основе анализировать эффект.

R>Мы же не штампуем целиком проекты, мы пишем отдельные функции — вот тут функци, которая форвардит вызов другой, а вот тут функция, которая вызывает ещё 3 функции, а вот тут функция, которая выделяет ресурс и т.д.


Пустые функции — это не то. Ну сколько можно, право. Даже уже занятие ebp уменьшает вычислительный потенциал на несколько процентов.

R>>>з.ы. кстати, если в функции нет объектов с нетривиальными деструкторами, то исключения выглядят значительно привлекательнее, т.к. и эпилога/пролога нет и вызовы функции дешевле.


AS>>Не вышлядят. Блин, ну сколько можно — я ж уже показал, что в этом случае используется ebp стек фрейм. Попробуй лучше исследовать, как это влияет на перфоманс вычислительной функции, а?


R>А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.


Только ты показывал это на фикции — на пустых функциях. Которые к тому же можно оптимизировать в случае возвращаемых значений.

AS>>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


R>Так же как и возвращаемые значения. Очевидно. Осталось только понять как.


А для этого надо как минимум анализировать результирующий код — чего сделано не было совсем. Ведь так? Ведь в результате (на мой взгляд) ты получил не эффект от использования исключений, а сравнение теплого с мягким...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[11]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 12:32
Оценка: -1
AS>>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?

M>Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.


Ух ты. Т.е. в реальной жизни пользователь запускает программу и всегда попадает на минимум? Везет...

AS>>Да нет, я не настаиваю. Просто если ты хочешь называть это исследованием и чтобы его результаты имели практическую ценность и обоснованность — должен быть виден код, который приводит к таким результатам. Скажи честно, ты смотрел для каждого варианта то, что генерит компилятор на уровне ассемблера? Ты разбирался как каждый из них работает с исключениями и с возвращающими значениями и влияние этого на кодогенерацию в целом? А ведь это все нужно, чтобы не просто статистику поиметь, а сделать из нее выводы — самое ценное, что есть в исследовании. Я выводов пока (как и самого исследования) пока тут не вижу, уж извини.


M>То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?


Я где-то такое говорил?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 12:52
Оценка:
Здравствуйте, remark, Вы писали:

Пояснения:

// В этой точке мы имеем максимальный приоритет потока - 31
// Надо это для того, чтоб как можно меньше постороннего кода вщемилось в наш
// Оптимальные измерения будут на многоядерных машинах - там остальной код будет
// большей частью вытеснен на другие ядра. Для одноядерки это только несколько снизит 
// кол-во потоков.
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

// Гарантируем что ОС не перебросит поток на другое ядро - таким образом можно смело юзать
// rdtsc т.к. синхронизация TSC нас парить не будет
SetProcessAffinityMask (GetCurrentProcess (),1);

// Ну, это можно было и не делать - но пусть будет на всяк случай
SetThreadAffinityMask (GetCurrentThread (),1);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 13:17
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>Ну и где тут реальный код? С трансляцией исключений в собственнные и т.п.? Я не вижу поинта для сравенения, уж извини. Ведь проверка ошибок для этого и используется — чтобы на основе возвращаемого значения сформировать свое. В реальной ситуации с исключениями часто ровно та же задача — у нас есть набор наших исключений и нам надо "чужие" исключения привести к нашим.


R>>Ну хорошо, а ты что утверждаешь, что реальный код — это только код с трансляцией исключений?

R>>Я надеюсь, что нет. Тогда почему не начать с простого случая?
R>>Я тебя уверяю, что есть множество кода, который никакими трансляциями не занимается.

AS>А я тебя уверяю в обратном. Сравни std и com исключения. Обычно в проекте своя иерархия исключений, и они транслируются на разных уровнях вызова. Как в этом случае добиться преймущества от исключений на уровне вызова библиотечных методов\функций — вопрос интересный.


Я не говорю, что другого не бывает. Но бывает, что не транслируются. Но как мы поймём более сложный случай, если не поймём простой?


AS>>>>>Понятно. Ну, что ж, могу лишь сказать, что это по меньшей мере неверно. Надо привязывать поток к одному ядру и устанавливать приоритеты на реалтайм — тогда хоть как то можно говорить о нормальном измерении при помощи этой методики.


R>>>>Зачем привязывать к единственному ядру? Или ты боишься, что у меня часть вычислений убежало на соседний комп?


AS>>>Куда убежать??? Вероятно, про багу с рассинхронизаций rdtsc на разных ядрах ты не слышал?


R>>Нет, чтобы на одном ядре таймер сам с собой рассинхронизировался, я не слышал. А что такое бывает?


AS>А при чем тут один. Ты тестировал на одной конфигурации?


Я тестировал на двух машиных, на обоих одно ядро.



R>>>>Зачем поднимать приоритеты? Или ты думаешь, что поток с более высоким приоритетом будет выполняться быстрее?


AS>>> Круто.


R>>Вот я тоже так подумал.


AS>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?


Я сделал это вполне намеренно. Это вполне распространённый подход при замерах времени в условиях возникновения непредвиденных задержек.


R>>Мне не жалко трудов, просто проект получился достаточно наколеночный, т.к. когда я начинал, то не собирался делать что-то особо основательное. Но если ты так настаиваешь, сейчас всё это запакую и выложу.


AS>Да нет, я не настаиваю. Просто если ты хочешь называть это исследованием и чтобы его результаты имели практическую ценность и обоснованность — должен быть виден код, который приводит к таким результатам. Скажи честно, ты смотрел для каждого варианта то, что генерит компилятор на уровне ассемблера? Ты разбирался как каждый из них работает с исключениями и с возвращающими значениями и влияние этого на кодогенерацию в целом? А ведь это все нужно, чтобы не просто статистику поиметь, а сделать из нее выводы — самое ценное, что есть в исследовании. Я выводов пока (как и самого исследования) пока тут не вижу, уж извини.


Чего-чего, а ассемблера я нагляделся за эти дни. Нагляделся на создание фреймов исключений и проверки возвращаемых значений.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 13:24
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

R>>>>Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.


AS>>>Я хочу сказать, что там не 2-3 команды, а десяток довольно толстых как сточки зрения кода, так и данных, команд.


R>>>>Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.

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

R>>>>Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.


AS>>>Чушь. Твоя запись if (!fun()) return val как раз не общий случай. Его я могу оптимизировать до одной проверки на все функции. val1 = fun1() ... valn = funn(); return val1 | val2 | ... | valn. В принципе, это может сделать и сам компилятор (более того, он это хоть и коряво, на пытается при помощи setne сделать). И что это покажет? Я говорю — нужны реальные паттерны.


R>>Это не оптимизация общего случая — пример — вложенные ресурсы.


AS>Это оптимизация приведенного тобой примера, в которой переход не требуется вообще...


Это понятно, что этот код можно оптимизировать. Я даже больше тебе скажу — весь этот код можно вообще удалить, т.к. он ровном счётом ничего не делает. И мерить это потом. Вот круто. Одна функция выполняется 0, и другая 0.
Суть как раз в том и заключается, что этой оптимизации нет и я эмулирую рельный код, в котором таких оптимизаций не будет. Только я выкинул из него весь шум в виде реальной работы, чтобы не вносить "постоянную составляющую".


R>>Ну допустим, я бы потратил пол-года и переписал некий проект bla-bla с одной стратегии на другую и выдал бы в итоге, что с исключениями bla-bla стал работать на 1% быстрее и размер уменьшился на 2%. Ну и что? По-твоему это бы дало больше информации?


AS>Не проект. Надо выделить несколько функций различных классов, и уже на их основе анализировать эффект.


R>>Мы же не штампуем целиком проекты, мы пишем отдельные функции — вот тут функци, которая форвардит вызов другой, а вот тут функция, которая вызывает ещё 3 функции, а вот тут функция, которая выделяет ресурс и т.д.


AS>Пустые функции — это не то. Ну сколько можно, право. Даже уже занятие ebp уменьшает вычислительный потенциал на несколько процентов.


R>>>>з.ы. кстати, если в функции нет объектов с нетривиальными деструкторами, то исключения выглядят значительно привлекательнее, т.к. и эпилога/пролога нет и вызовы функции дешевле.


AS>>>Не вышлядят. Блин, ну сколько можно — я ж уже показал, что в этом случае используется ebp стек фрейм. Попробуй лучше исследовать, как это влияет на перфоманс вычислительной функции, а?


R>>А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.


AS>Только ты показывал это на фикции — на пустых функциях. Которые к тому же можно оптимизировать в случае возвращаемых значений.


Да, всё правильно. Теперь ты можешь добавить в эти пустые функции своё наполнение, прибавить ко всем цифрам постоянную составляющую и получить те же результаты, но с постоянной составляющей.


AS>>>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


R>>Так же как и возвращаемые значения. Очевидно. Осталось только понять как.


AS>А для этого надо как минимум анализировать результирующий код — чего сделано не было совсем. Ведь так? Ведь в результате (на мой взгляд) ты получил не эффект от использования исключений, а сравнение теплого с мягким...


Смотрел-смотрел. Просто я думал, что такой объём кода и так смотреть никто не бует, к тому же время уже подходило к часу ночи — хотелось домой


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: Конструктив
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 13:26
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


Давай же сформируем эти "общие паттерны". Как ты их себе видишь?
Я думаю, их будет полезно обсудить — все выскажут свои мысли. К тому же приверженцы обоих лагерей смогут предложить лучшие реализации того и другого подхода — чтобы никому не было обидно.




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 13:40
Оценка:
R>>>А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.

AS>>Только ты показывал это на фикции — на пустых функциях. Которые к тому же можно оптимизировать в случае возвращаемых значений.


R>Да, всё правильно. Теперь ты можешь добавить в эти пустые функции своё наполнение, прибавить ко всем цифрам постоянную составляющую и получить те же результаты, но с постоянной составляющей.


Не получишь. Как минимум в одном случае у тебя на один рабочий регистр меньше — соответственно, меньше и производительность самой функции (а не пустышки). Право, я уже устал это повторять.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: Конструктив
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 14:01
Оценка:
AS>>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.

R>Давай же сформируем эти "общие паттерны". Как ты их себе видишь?


Давай. Навскидку я вижу следующие паттерны:
1. Чисто вычислительная функция — когда вызовов апи не производится вообще. Это может быть быть парсер текста, вычисление с использованием матриц и т.п. Желательно распределить их по степени сложности — глубины вызовов и количеству вызовов с проверками в одной функции.
2. Обертки1. Когда ровно один слой и все сводится к вызову апи функции (или метода) и проверке возвращаемого значения\трансляции в исключение.
3. Обертки1. Тоже ровно один слой, но в этом случае апи использует исключение (пример — MFC). Мы транслируем в свое исключение либо в код ошибки\возвращаемое значение.
4. Работа с файлами и анализ текста. Микс тест из 1, 2 и 3.
5. Смешанные вычисления — когда необходимо в процессе вычислений обращаться к апи. Сложность вычислений,процент обращений и характер распределения мест обработки по уровням можно регулировать (либо определить статистически общие варианты и использовать только их).

Наверное, можно придумать еще кучу паттернов, используемых наиболее часто, либо параметризировать эти с учетом статистики.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 14:13
Оценка:
Здравствуйте, remark, Вы писали:

[]

R>

Размер кода


R>Так же есть ещё один аспект, влияющий на производительность, но который ускользает при таких замерах – размер сгенерированного кода. Чем больше кода – тем больше промахов кэша и переходов через границы страницы памяти – это может достаточно сильно влиять на производительность. Соответственно я замерил размер кода для одной функции типа f6(), которые я приводил выше. Результаты:

R>
с с++/rvс++/ex
instr 386 442 232
size 1320 2359 1329

R>Замерял на msvc71. instr – кол-во ассемблерных команд. Size – размер функции в байтах.

R>У исключений значительно меньше инструкций, тем не менее размер кода равен размеру кода на С с возвращаемыми значениями. Как ни странно... Связано с тем, что команды там больше по размеру. Код на С++ с возвращаемыми значениями тут сильно проигрывает – так там инструкции и на проверки возвращаемых значений и на поддержку исключений.


Интересно, почему С++ с возвращаемыми значениями так сильно проиграл С? А мне кажется, я знаю причину — оптимизатор MSVC отвратительно работает с bool типами, замена на int даёт выигрыш.

[]

R>

smart_ptr vs. smart_ptr&


Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 14:27
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

CC>Увы, но более точного метода измерения кроме как

CC>
CC>    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
CC>    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
CC>

CC>и rdtsc пока ИМХО никто не предложил...

Как минимум, можно использовать ещё и счётчики производительности (GetProcessTimes, NtQueryInformationThread + ThreadTimes). Даже без RDTSC погрешность измерения примерно равна длительности кванта планировщика (1-15 мс), что может оказаться лучше чем у способа выше, где она неизвестно какая
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 14:41
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...

Однако... Это на каком компилере?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 16:04
Оценка:

Exceptions vs. Return Values


Привожу полный код теста (для msvc):

файл 1.cpp:
#include <iostream>

typedef unsigned __int64 tick_t;
tick_t const max_tick = static_cast<tick_t>(-1);
__declspec(naked) tick_t get_tc()
{
    __asm rdtsc;
    __asm ret;
}

volatile int counter = 0;

struct tobj
{
    __declspec(noinline) tobj();
    __declspec(noinline) ~tobj();
    int fake;
};

__declspec(noinline) bool ctor(int*);
__declspec(noinline) void dtor(int*);

__declspec(noinline) void test_ex2()
{
    if (!++counter) throw 0;
}

__declspec(noinline) void test_ex()
{
    tobj o1, o2, o3, o4;
    test_ex2();
    test_ex2();
    test_ex2();
    test_ex2();
}

__declspec(noinline) bool test_rv2()
{
    return !!++counter;
}

__declspec(noinline) bool test_rv()
{
    int o1, o2, o3, o4;
    bool res = true;
    if (!ctor(&o1)) goto end;
    if (!ctor(&o2)) goto do1;
    if (!ctor(&o3)) goto do2;
    if (!ctor(&o4)) goto do3;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    res = true;
do4:    dtor(&o4);
do3:    dtor(&o3);
do2:    dtor(&o2);
do1:    dtor(&o1);
end:    return res;
}

int main()
{
    int const test_count = 10000;

    {
        int ec = 0;
        tick_t time = max_tick;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            try
            {
                test_ex();
            }
            catch (...)
            {
                ++ec;
            }
            t = get_tc() - start;
            if (t < time) time = t;
        }
        std::cout << "test_ex: " << time << "\n";
    }

    {
        int ec = 0;
        tick_t time = max_tick;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            if (!test_rv())
                ++ec;
            t = get_tc() - start;
            if (t < time) time = t;
        }
        std::cout << "test_rv: " << time << "\n";
    }
}




файл 2.cpp:
struct tobj
{
    __declspec(noinline) tobj();
    __declspec(noinline) ~tobj();
};

tobj::tobj() {}
tobj::~tobj() {}

__declspec(noinline) bool ctor(int*) {return true;}
__declspec(noinline) void dtor(int*) {}




Листинг:
__declspec(noinline) void test_ex()
{
// Вот создаём фрейм - 6 команд
00401040  push        0FFFFFFFFh 
00401042  push        offset __ehhandler$?test_ex@@YAXXZ (401750h) 
00401047  mov         eax,dword ptr fs:[00000000h] 
0040104D  push        eax  
0040104E  mov         dword ptr fs:[0],esp 
00401055  sub         esp,10h 
    tobj o1, o2, o3, o4;
// Вот вызываем 4 конструктора - 4 по 3 команды
00401058  lea         ecx,[esp+0Ch] 
0040105C  call        tobj::tobj (401300h) 
00401061  lea         ecx,[esp+8] 
00401065  mov         dword ptr [esp+18h],0 
0040106D  call        tobj::tobj (401300h) 
00401072  lea         ecx,[esp+4] 
00401076  mov         byte ptr [esp+18h],1 
0040107B  call        tobj::tobj (401300h) 
00401080  lea         ecx,[esp] 
00401083  mov         byte ptr [esp+18h],2 
00401088  call        tobj::tobj (401300h) 
0040108D  mov         byte ptr [esp+18h],3 
// Вот вызываем 4 функции - 4 команды
    test_ex2();
00401092  call        test_ex2 (401010h) 
    test_ex2();
00401097  call        test_ex2 (401010h) 
    test_ex2();
0040109C  call        test_ex2 (401010h) 
    test_ex2();
004010A1  call        test_ex2 (401010h) 
}
// Вызываем 4 деструктора - 4 по 3 инструкции
004010A6  lea         ecx,[esp] 
004010A9  mov         byte ptr [esp+18h],2 
004010AE  call        dtor (401320h) 
004010B3  lea         ecx,[esp+4] 
004010B7  mov         byte ptr [esp+18h],1 
004010BC  call        dtor (401320h) 
004010C1  lea         ecx,[esp+8] 
004010C5  mov         byte ptr [esp+18h],0 
004010CA  call        dtor (401320h)
// Снимаем фрейм исключений - 6 инструкций 
004010CF  lea         ecx,[esp+0Ch] 
004010D3  mov         dword ptr [esp+18h],0FFFFFFFFh 
004010DB  call        dtor (401320h) 
004010E0  mov         ecx,dword ptr [esp+10h] 
004010E4  mov         dword ptr fs:[0],ecx 
004010EB  add         esp,1Ch 
004010EE  ret




__declspec(noinline) bool test_rv()
{
    int o1, o2, o3, o4;
    bool res = true;
    if (!ctor(&o1)) goto end;
// Вызываем 4 конструктора - 4 по 6 инструкций
00401110  lea         eax,[esp-4] 
00401114  sub         esp,10h 
00401117  push        eax  
00401118  call        ctor (401310h) 
0040111D  add         esp,4 
00401120  test        al,al 
00401122  je          do1+0Dh (4011ADh) 
    if (!ctor(&o2)) goto do1;
00401128  lea         ecx,[esp+8] 
0040112C  push        ecx  
0040112D  call        ctor (401310h) 
00401132  add         esp,4 
00401135  test        al,al 
00401137  je          do1 (4011A0h) 
    if (!ctor(&o3)) goto do2;
00401139  lea         edx,[esp+4] 
0040113D  push        edx  
0040113E  call        ctor (401310h) 
00401143  add         esp,4 
00401146  test        al,al 
00401148  je          do2 (401193h) 
    if (!ctor(&o4)) goto do3;
0040114A  lea         eax,[esp] 
0040114D  push        eax  
0040114E  call        ctor (401310h) 
00401153  add         esp,4 
00401156  test        al,al 
00401158  je          do3 (401186h) 

// Вызываем 4 функции - 4 по 3 инструкции
    if (!test_rv2()) goto do4;
0040115A  call        test_rv2 (4010F0h) 
0040115F  test        al,al 
00401161  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
00401163  call        test_rv2 (4010F0h) 
00401168  test        al,al 
0040116A  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
0040116C  call        test_rv2 (4010F0h) 
00401171  test        al,al 
00401173  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
00401175  call        test_rv2 (4010F0h) 
    res = true;
// Вызываем 4 деструктора - 4 по 4 инструкции
do4:    dtor(&o4);
0040117A  lea         ecx,[esp] 
0040117D  push        ecx  
0040117E  call        dtor (401320h) 
00401183  add         esp,4 
do3:    dtor(&o3);
00401186  lea         edx,[esp+4] 
0040118A  push        edx  
0040118B  call        dtor (401320h) 
00401190  add         esp,4 
do2:    dtor(&o2);
00401193  lea         eax,[esp+8] 
00401197  push        eax  
00401198  call        dtor (401320h) 
0040119D  add         esp,4 
do1:    dtor(&o1);
004011A0  lea         ecx,[esp+0Ch] 
004011A4  push        ecx  
004011A5  call        dtor (401320h) 
004011AA  add         esp,4 
end:    return res;
004011AD  mov         al,1 
}
004011AF  add         esp,10h 
004011B2  ret




Итого время выполнения:
ex — 172
rv — 184



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 16:09
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Интересно, почему С++ с возвращаемыми значениями так сильно проиграл С? А мне кажется, я знаю причину — оптимизатор MSVC отвратительно работает с bool типами, замена на int даёт выигрыш.



Нет, там проблема не в этом.
Там проблема, в том, что есть деструкторы — значит устанавливается и снимается фрейм исключений — т.е. тут двойная работа.
А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Ассемблер для Andrew S
От: Аноним  
Дата: 02.04.07 16:18
Оценка:
Здравствуйте, remark, Вы писали:

R>

Exceptions vs. Return Values


R>Привожу полный код теста (для msvc):


R>файл 1.cpp:

R>
R>#include <iostream>

R>typedef unsigned __int64 tick_t;
R>tick_t const max_tick = static_cast<tick_t>(-1);
R>__declspec(naked) tick_t get_tc()
R>{
R>    __asm rdtsc;
R>    __asm ret;
R>}


Кстати rdtsc темное место на многоядерных и винапи коунтеры тоже
Re[3]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 17:03
Оценка:
Здравствуйте, remark, Вы писали:

R>Там проблема, в том, что есть деструкторы — значит устанавливается и снимается фрейм исключений — т.е. тут двойная работа.


Я о "с++/rv"

R>А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.


Не верю Компилятор там один и тот же.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: MSVC 2005 [-]
От: gear nuke  
Дата: 02.04.07 17:23
Оценка:
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 17:29
Оценка: +1
[code skipped]

Нда, сильно. Вот почему я и говорю о необходимости кода.
1. Тест в общем случае некорректен. В случае использования возвращаемого значения использовать идиому RAI нет необходимости, поэтому первые 4 сравнения идут лесом. Про что я и говорил — различные варианты обработки ошибок влекут использование различных паттернов на различных уровнях вызова.
2. Вариант с rv у тебя с ошибкой
3. Где случай, в котором тебе надо вызывать функцию вне зависимости от результата вызова предыдущей? Т.е. вызвали одну, затем другую, затем третью и т.д. — а потом обрабатываем результат в зависимости от вызова. Т.е. не &&, а ||.
4. Где вложенная обработка исключений, тоже непонятно. Впрочем, это боком относится к (3), но все же? Например, некоторые искючения могут позволить продолжить цикл (info\warning), тогда как другие ведут к выходу.
5. Обрати внимание, что в rv варианте используется esp стек фрейм, а в ex — может и ebp. О чем я тебе уже 100 раз говорил. Итого — мало-мальски сложный код в ex модели будет тормознее, чем в rv. Тот пример у тебя, слишком прост, чтобы это отобразить. Вот, посмотри, что получается в этом случае:


static void test_ex()
{
    tobj o1, o2, o3, o4;
    try
    {
        test_ex2();
        test_ex2();
        test_ex2();
        test_ex2();
    }
    catch(...)
    {
    }
}


6. Обрати внимание на разницу в способе вызова — в случае ex для настоящих объектов у тебя используеся this_call. Попробуй сделать не эмуляцию контрукторов функциями, а сделать init\deinit в самом tobj. Это съэкономит прилично и места, и времени.
7. Исключения должны быть более сложными — иметь иерархию классов — про это уже говорили. Это позволит устроить уровни отсечения.

А вообще, проблема на мой взгляд вот в чем. Ты берешь за основу модель исключений, и пытаешься приспособить под нее модель возвращаемых значений. Об этом говорит и использование bool в качестве возвращаемого значения (тогда как используется обычно более информативные типы, возвращающие не только успешность, но и саму ошибку — т.е. информации в разы больше), и построение функции (очередность и кратность вызова), уровень обработки (исключение у тебя обрабатывается на самом высоком уровне, тогда как общая практика — обработка части исключений на различных уровнях вызова, добавление отработки даже на одном уровне — то, что ты называешь ресурсами, уже изменяет ситуацию) и т.д. Неудивительно, что в этих условиях rv почти всегда проигрывает. У тебя полностью сферический конь в полном отсутствии воздуха. Я уже неоднократно говорил, что придумать ситуации, когда ex или rv будет выигрывать проблем не составляет. Нас должно интересовать не это, а реально существующие паттерны кода.

PS Эк тебя зацепило Критику надо воспринимать не в штыки, а пытаться хотя бы слушать оппонента.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 17:51
Оценка: 1 (1) +1
Здравствуйте, Andrew S, Вы писали:

AS>>>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?


M>>Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.


AS>Ух ты. Т.е. в реальной жизни пользователь запускает программу и всегда попадает на минимум? Везет...


Нет , тут дело в методике измерений. Есть масса причин для замедления времени выполнения (прерывания и т.п.), но нет ни ЕДИНОЙ причины , для того чтобы код выполнялся быстрее в какой то из разов.


M>>То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?


AS>Я где-то такое говорил?


По постам сложилось впечатление , раз вы знаете и умеете все лучше чем автор топика.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 18:09
Оценка: 1 (1)
Здравствуйте, gear nuke, Вы писали:

GN>Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...


1 — передача адреса без чтония памяти. la заместо mov
2 — Может E(ABCD)X кончильсь, а указатели остались.
3 — Уж во всяком случае не всегда так
Re[13]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 18:11
Оценка:
AS>>>>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?

M>>>Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.


AS>>Ух ты. Т.е. в реальной жизни пользователь запускает программу и всегда попадает на минимум? Везет...


M>Нет , тут дело в методике измерений. Есть масса причин для замедления времени выполнения (прерывания и т.п.), но нет ни ЕДИНОЙ причины , для того чтобы код выполнялся быстрее в какой то из разов.


Ух ты какое сильное заявление. Причин может быть куча — выполнение на разных процессорах, состояние кеш-памяти, размер физической памяти и файла подкачки и многое многое другое. Все это может вести к выпадениям как меньшую, так и в большую сторону, тогда как в 99% процентах случаев разброс будет около некоей средней величины. Или опять интересует поведение сферического коня в вакууме? Тогда лучше всего в этом смысле тестировать в системах типа DOS. А тут же обычная практика — отсечение значений, которые выходят за некоторую границу (как сверху, так и снизу), и вычисление среднего относительно остальных.

M>>>То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?


AS>>Я где-то такое говорил?


M>По постам сложилось впечатление , раз вы знаете и умеете все лучше чем автор топика.


Фраза как минимум несогласована — моя твоя есть с трудом понимайт. Ну а касательно ваших впечатлений — ну это сугубо ваше дело, зачем это на форум то писать? Есть конструктив по поводу тестов? У меня вот есть. А у вас?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[14]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 18:16
Оценка:
Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[15]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 18:33
Оценка:
M>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.

Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 18:57
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>1 — передача адреса без чтония памяти. la заместо mov


Имеется ввиду команда lea? Не пойму, как она может быть лучше.

А>2 — Может E(ABCD)X кончильсь, а указатели остались.


Указатели, как и данные, могут храниться в любом регистре.

Но речь о случае, когда данные (а тем более указатели) вообще не нужно передавать посредством копирования, в функциях вида:
template <typename T>
static inline
bool f(T a, T a2) { return f_impl(a, a2); }
вообще никакой код не должен быть сгенерирован. В современном коде часто встречаются многократные вложения таких примитивных функций, и оптимизатор сдаёт, делая лишние копирования в регистры даже при inline подстановке функций для типа int.

Ещё хуже для UDT типов малого размера (как раз смартпоинтеры)
struct  { int _; };
Вполне можно работать с этим типом как с простым int, но компилятор опять же вставляет лишние копирования.

Вот только вчера столкнулся с растущим отсюда багом:

struct kirql { uint8_t level; };

extern "C" __declspec(dllimport)
void __fastcall
  KfReleaseSpinLock(
    kspin_lock *  SpinLock,
    const kirql   NewIrql
    );

void kspin_lock::release(const kirql new_irql)
{
  KfReleaseSpinLock(this, new_irql);
}

При удачной оптимизации это компелируется (и должно!) в:
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z PROC   ; ntl::km::kspin_lock::release, COMDAT
; _this$ = ecx
; Line 71
    jmp DWORD PTR __imp_@KfReleaseSpinLock@8
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z ENDP   ; ntl::km::kspin_lock::release

Однако при отключенной (дебаг) получается чушь:
_this$ = -4                     ; size = 4
_new_irql$ = 8                      ; size = 1
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z PROC   ; ntl::km::kspin_lock::release, COMDAT
; _this$ = ecx
; Line 70
    push    ebp
    mov ebp, esp
    push    ecx
    mov DWORD PTR _this$[ebp], ecx
; Line 71
    mov al, BYTE PTR _new_irql$[ebp]
    push    eax                  ; вот этот параметр следует передавать в регисте edx, а не через стек 
    mov ecx, DWORD PTR _this$[ebp]
    call    DWORD PTR __imp_@KfReleaseSpinLock@8
; Line 72
    mov esp, ebp
    pop ebp
    ret 4
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z ENDP   ; ntl::km::kspin_lock::release
; Function compile flags: /Odtp
_TEXT   ENDS


А>3 — Уж во всяком случае не всегда так


Ну да, часто нет разницы
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[16]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 19:48
Оценка:
Здравствуйте, Andrew S, Вы писали:

M>>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.


AS>Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?


начать можно тут
http://www.codenet.ru/progr/optimize/kk/
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[17]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 20:07
Оценка:
M>>>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.

AS>>Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?


M>начать можно тут

M>http://www.codenet.ru/progr/optimize/kk/

И что там я обнаружу нового?
Вот цитата:

Непосредственные результаты замеров времени исполнения программы в "сыром" виде, как было показано выше, ни на что ни годны. Очевидно, перед использованием их следует обработать. Как минимум откинуть пограничные значения, вызванные нерегулярными наведенными эффектами (ну, например, в самый ответственный для профилировки момент, операционная система принялась что-то сбрасывать на диск), а затем... Затем перед нами встает Буриданова проблема . Мы будем должны либо выбрать результат с минимальным временем исполнения — как наименее подвергнувшийся пагубному влиянию многозадачности, либо же вычислить наиболее типичное время выполнения — как время выполнения в реальных, а не идеализированных "лабораторных" условиях.

Мной опробован и успешно применяется компромиссный вариант, комбинирующий оба этих метода. Фактически, я предлагаю вам отталкиваться от среднеминимального времени исполнения. Сам алгоритм в общих чертах выглядит так: мы выполняем N повторов программы, а затем отбрасываем N/3 максимальных и N/3 минимальных результатов замеров. Для оставшихся N/3 замеров мы находим среднее арифметическое, которое и берем за основной результат. Величина N варьируется в зависимости от конкретной ситуации, но обычно с лихвой хватает 9-12 повторов, т. к. большее количество уже не увеличивает точности результатов.


Ничего не напоминает? А рассуждения о том, что минимальное время выполнения зависит только от программного окружения — очень и очень спорно. Особенно при наличии многопроцессорных и неюниформных юнитов.
Кстати, там же и про RDTSC есть и про то, что и как он меряет. И почему то, что автора топика, неправильно. И читать это полезно как раз не мне (хотя мне это и интересно, впрочем, статью эту я уже читал), а автору топика и тестов...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[18]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 03.04.07 04:38
Оценка:
Теперь по крайней мере вы знаете, чем обусловленно стремление брать минимальное время.

А то что вопрос неоднозначен я знаю. Автору топика возможно это будет интерессно, но я бы вам предложил поправить замеры времени в коде , который он сибирался выложить.
Заранее спасибо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Ассемблер для Andrew S
От: minorlogic Украина  
Дата: 03.04.07 04:38
Оценка:
Ждем вашу версию исправленную
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Ассемблер для Andrew S
От: CreatorCray  
Дата: 03.04.07 06:25
Оценка: +1
Здравствуйте, remark, Вы писали:

Бугага! Тест то некорректен... Ну как можно мешать в одном exeшнике два теста которые требуют разных опций компиляции. Ладно б оптимизации так ведь исключений...

Раздели на 2 отдельных Exe шника
один с /EHsc и кодом основанным на исключениях
другой без и с кодом на return value
надо это для того, чтоб в rv тесте не было ничего связанного с исключениями.

запускай их РАЗДЕЛЬНО.

мои результаты:
test_ex: 127
test_rv: 120

Чуть модифицировал тест с целью посмотреть не на минимум а на полное время выполнения — читай среднее время выполнения

int main()
{
    int const test_count = 1000000;

#if 1
    {
        int ec = 0;
        tick_t time = 0;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            try
            {
                test_ex();
            }
            catch (...)
            {
                ++ec;
            }
            t = get_tc() - start;
            time += t;
        }
        std::cout << "test_ex: " << time << "\n";
    }
#else
    {
        int ec = 0;
        tick_t time = 0;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            if (!test_rv())
                ++ec;
            t = get_tc() - start;
            time += t;
        }
        std::cout << "test_rv: " << time << "\n";
    }
#endif
}


test_ex: 137504231
test_rv: 125761239

в среднем получается:

test_ex: 137
test_rv: 125

Ну как ни крути — у rv время меньше...

Опции компиляции: Intel C++ 9.1
icl /c /O3 /Og /Ob2 /Oi /Ot /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MT /YX"StdAfx.h" /Fp".\Release/test.pch" /FAcs /Fa".\Release/" /Fo".\Release/" /W3 /nologo /Zi /Gd /QxP
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 08:28
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, remark, Вы писали:


R>>Там проблема, в том, что есть деструкторы — значит устанавливается и снимается фрейм исключений — т.е. тут двойная работа.


GN>Я о "с++/rv"


Ну так исключение всё равно может полететь, и деструкторы есть, значит фрейм всё равно надо устанавливать.

R>>А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.


GN>Не верю Компилятор там один и тот же.


В С — там код более явный, поэтому у компилятора меньше свободы, а в С++ менее явный — и у компилятора больше свободы.
Я глядел сгенерированный код "с++/rv" — я там даже сразу не понял, что он там к чему нагенерил — там он как-то хитро пишет прям в стек, т.е. не push/pop, а mov [sp],x и всякого такого рода вещи.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 08:33
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Однако при отключенной (дебаг) получается чушь:


Ну под дебагом-то что код смотреть? Ты приведи пример, где под релизом так.

В msvc помогает "добить" такие места, где не идельная оптимизация, включение link-time code generation — он как раз вот такие "форварды" должен элиминировать.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 08:45
Оценка:
M>Ждем вашу версию исправленную

Вы мне предлагаете написать набор паттернов? Вроде как не я затевал эту тему
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 08:50
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>[code skipped]


AS>Нда, сильно. Вот почему я и говорю о необходимости кода.

AS>1. Тест в общем случае некорректен. В случае использования возвращаемого значения использовать идиому RAI нет необходимости, поэтому первые 4 сравнения идут лесом. Про что я и говорил — различные варианты обработки ошибок влекут использование различных паттернов на различных уровнях вызова.

Ну так этот код был в изначальном посте. Я б не воспринимал в штыки, если б ты сразу написал, что с использованием возвращаемых значений пишут вот так-то и так-то, вот код. Кстати, и тут тоже кода нет, я не умею читать мысли — напиши уже давно свой вариант кода, а не вокруг да около.

AS>2. Вариант с rv у тебя с ошибкой


Бывает...
действительно bool res = fasle

AS>3. Где случай, в котором тебе надо вызывать функцию вне зависимости от результата вызова предыдущей? Т.е. вызвали одну, затем другую, затем третью и т.д. — а потом обрабатываем результат в зависимости от вызова. Т.е. не &&, а ||.

AS>4. Где вложенная обработка исключений, тоже непонятно. Впрочем, это боком относится к (3), но все же? Например, некоторые искючения могут позволить продолжить цикл (info\warning), тогда как другие ведут к выходу.

А если бы я привёл тот случай, ты бы сказал, а где у тебя этот случай
Что значит, где другой случай? Вот есть этот случай, я его тестирую. У меня в коде, по крайней мере, такие паттерны есть. Мне этого достаточно. По крайней мере для начала.


AS>5. Обрати внимание, что в rv варианте используется esp стек фрейм, а в ex — может и ebp. О чем я тебе уже 100 раз говорил.


Ни там, ни там не вижу использования ebp.
Приведи код и листинг. А то сейчас такое ощущение, что ты код не смотрел.


AS>6. Обрати внимание на разницу в способе вызова — в случае ex для настоящих объектов у тебя используеся this_call. Попробуй сделать не эмуляцию контрукторов функциями, а сделать init\deinit в самом tobj. Это съэкономит прилично и места, и времени.


Не понял. Приведи код, а то ещё долго будем припираться...


AS>А вообще, проблема на мой взгляд вот в чем. Ты берешь за основу модель исключений, и пытаешься приспособить под нее модель возвращаемых значений. Об этом говорит и использование bool в качестве возвращаемого значения (тогда как используется обычно более информативные типы, возвращающие не только успешность, но и саму ошибку — т.е. информации в разы больше), и построение функции (очередность и кратность вызова), уровень обработки (исключение у тебя обрабатывается на самом высоком уровне, тогда как общая практика — обработка части исключений на различных уровнях вызова, добавление отработки даже на одном уровне — то, что ты называешь ресурсами, уже изменяет ситуацию) и т.д. Неудивительно, что в этих условиях rv почти всегда проигрывает. У тебя полностью сферический конь в полном отсутствии воздуха. Я уже неоднократно говорил, что придумать ситуации, когда ex или rv будет выигрывать проблем не составляет. Нас должно интересовать не это, а реально существующие паттерны кода.


Это вполне реальный паттерн. Нет преобразования исключений. Исключений говорит о неудачности транзакции. Нет никаких частичных восстановлений и фаиловер. У меня лично такого кода очень много и я знаю, что и у других тоже. Я хочу мерить это.


AS>PS Эк тебя зацепило Критику надо воспринимать не в штыки, а пытаться хотя бы слушать оппонента.


Тебя приходится не слушать, а гадать и вытягивать. Код был в первом посте — приведи наконец свой код.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[19]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 08:50
Оценка:
M>Теперь по крайней мере вы знаете, чем обусловленно стремление брать минимальное время.

Теперь? Автор топика сразу сказал, почему он берет минимальное время. Впрочем, обе стратегии в обычных условиях показывают некую тенденцию, а то, что тесты не совсем корректны — думаю, уже убедились. Так что надо смотреть код, как я неоднократно говорил — почему, например, автор не заметил, что вариант с rv используется другую спецификацию вызовов для эмуляции конструкторов\деструкторов? А это по 4 команды на каждый вызов, причем 2 из них — работы с памятью. Нормально так, да?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 08:52
Оценка:
CC>Бугага! Тест то некорректен... Ну как можно мешать в одном exeшнике два теста которые требуют разных опций компиляции. Ладно б оптимизации так ведь исключений...

Это да. Но все-же имхо это не должно в данном случае... хотя, нет, должно, в смысле, может. Выравнивание.

CC>мои результаты:

CC>test_ex: 127
CC>test_rv: 120

А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 08:59
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, remark, Вы писали:


CC>Бугага! Тест то некорректен... Ну как можно мешать в одном exeшнике два теста которые требуют разных опций компиляции. Ладно б оптимизации так ведь исключений...


CC>Раздели на 2 отдельных Exe шника

CC>один с /EHsc и кодом основанным на исключениях
CC>другой без и с кодом на return value
CC>надо это для того, чтоб в rv тесте не было ничего связанного с исключениями.

CC>запускай их РАЗДЕЛЬНО.


CC>мои результаты:

CC>test_ex: 127
CC>test_rv: 120

CC>Чуть модифицировал тест с целью посмотреть не на минимум а на полное время выполнения — читай среднее время выполнения


CC>test_ex: 137504231

CC>test_rv: 125761239

CC>в среднем получается:


CC>test_ex: 137

CC>test_rv: 125

CC>Ну как ни крути — у rv время меньше...


CC>Опции компиляции: Intel C++ 9.1

CC>icl /c /O3 /Og /Ob2 /Oi /Ot /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MT /YX"StdAfx.h" /Fp".\Release/test.pch" /FAcs /Fa".\Release/" /Fo".\Release/" /W3 /nologo /Zi /Gd /QxP


Скомпилировал код с возвращаемыми значениями как С-код:
test_ex: 172
test_rv: 184

Если суммировать:
test_ex: 1793656
test_rv: 1853848

Вот поэтому и было бы хорошо сделать "коробочный" тест, который можно было бы легко скачать, скомпилировать, запустить и выложить результаты для своей платформы.


з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 09:14
Оценка:
AS>>3. Где случай, в котором тебе надо вызывать функцию вне зависимости от результата вызова предыдущей? Т.е. вызвали одну, затем другую, затем третью и т.д. — а потом обрабатываем результат в зависимости от вызова. Т.е. не &&, а ||.
AS>>4. Где вложенная обработка исключений, тоже непонятно. Впрочем, это боком относится к (3), но все же? Например, некоторые искючения могут позволить продолжить цикл (info\warning), тогда как другие ведут к выходу.

R>А если бы я привёл тот случай, ты бы сказал, а где у тебя этот случай


Так можно сделать оба? Или это будет слишком плохо для исключений, да?

R>Что значит, где другой случай? Вот есть этот случай, я его тестирую. У меня в коде, по крайней мере, такие паттерны есть. Мне этого достаточно. По крайней мере для начала.


Понятно.

AS>>5. Обрати внимание, что в rv варианте используется esp стек фрейм, а в ex — может и ebp. О чем я тебе уже 100 раз говорил.


R>Ни там, ни там не вижу использования ebp.

R>Приведи код и листинг. А то сейчас такое ощущение, что ты код не смотрел.

Код я тебе привел. Держи листинг...

?test_ex@@YAXXZ PROC NEAR                ; test_ex, COMDAT

; 467  : {

    push    ebp
    mov    ebp, esp
    push    -1
    push    $L107950
    mov    eax, DWORD PTR fs:__except_list
    push    eax
    mov    DWORD PTR fs:__except_list, esp
    sub    esp, 20                    ; 00000014H
    push    ebx
    push    esi
    push    edi

; 468  :     tobj o1, o2, o3, o4;

    lea    ecx, DWORD PTR _o1$[ebp]
    mov    DWORD PTR __$EHRec$[ebp], esp
    call    ??0tobj@@QAE@XZ                ; tobj::tobj
    lea    ecx, DWORD PTR _o2$[ebp]
    mov    DWORD PTR __$EHRec$[ebp+12], 0
    call    ??0tobj@@QAE@XZ                ; tobj::tobj
    lea    ecx, DWORD PTR _o3$[ebp]
    mov    BYTE PTR __$EHRec$[ebp+12], 1
    call    ??0tobj@@QAE@XZ                ; tobj::tobj
    lea    ecx, DWORD PTR _o4$[ebp]
    mov    BYTE PTR __$EHRec$[ebp+12], 2
    call    ??0tobj@@QAE@XZ                ; tobj::tobj

; 469  :     try
; 470  :     {

    mov    BYTE PTR __$EHRec$[ebp+12], 4

; 471  :         test_ex2();

    call    ?test_ex2@@YAXXZ            ; test_ex2

; 472  :         test_ex2();

    call    ?test_ex2@@YAXXZ            ; test_ex2

; 473  :         test_ex2();

    call    ?test_ex2@@YAXXZ            ; test_ex2

; 474  :         test_ex2();

    call    ?test_ex2@@YAXXZ            ; test_ex2
$L105166:

; 479  : }

    lea    ecx, DWORD PTR _o4$[ebp]
    mov    DWORD PTR __$EHRec$[ebp+12], 2
    call    ??1tobj@@QAE@XZ                ; tobj::~tobj
    lea    ecx, DWORD PTR _o3$[ebp]
    mov    BYTE PTR __$EHRec$[ebp+12], 1
    call    ??1tobj@@QAE@XZ                ; tobj::~tobj
    lea    ecx, DWORD PTR _o2$[ebp]
    mov    BYTE PTR __$EHRec$[ebp+12], 0
    call    ??1tobj@@QAE@XZ                ; tobj::~tobj
    lea    ecx, DWORD PTR _o1$[ebp]
    mov    DWORD PTR __$EHRec$[ebp+12], -1
    call    ??1tobj@@QAE@XZ                ; tobj::~tobj
    mov    ecx, DWORD PTR __$EHRec$[ebp+4]
    pop    edi
    pop    esi
    mov    DWORD PTR fs:__except_list, ecx
    pop    ebx
    mov    esp, ebp
    pop    ebp
    ret    0


Тот код, что у тебя, слишком прост, чтобы начать пользовать ebp, я это уже тебе написал.

AS>>6. Обрати внимание на разницу в способе вызова — в случае ex для настоящих объектов у тебя используеся this_call. Попробуй сделать не эмуляцию контрукторов функциями, а сделать init\deinit в самом tobj. Это съэкономит прилично и места, и времени.


R>Не понял. Приведи код, а то ещё долго будем припираться...


А что тут понимать? Если бы ты смотрел сгенеренный код:
ex:
    lea    ecx, DWORD PTR _o3$[ebp]
    mov    BYTE PTR __$EHRec$[ebp+12], 1
    call    ??0tobj@@QAE@XZ                ; tobj::tobj

rv:

    lea    ecx, DWORD PTR _o2$[esp+20]
    push    ecx
    call    ?ctor@@YA_NPAH@Z            ; ctor
    add    esp, 4
    test    al, al
    je    SHORT $L105177


Видишь, в одном случае параметр (this) передается в eсx, а во втором — через стек?

Вот как правильно (в смысле, соответствует твоему варианту теста):

struct tobj1
{
    bool init();
    void release();
    int fake;
};

bool tobj1::init() {return true;}
void tobj1::release() {}

static bool test_rv()
{
    tobj1 o1, o2, o3, o4;
    bool res = false;
    if (o1.init())
    {
        if (o2.init())
        {
            if (o3.init())
            {
                if (o4.init())
                {
                    res = test_rv2() && test_rv2() && test_rv2() && test_rv2();
                    o4.release();
                }
                o3.release();
            }
            o2.release();
        }
        o1.release();
    }
    return res;
}


    lea    ecx, DWORD PTR _o3$[esp+20]
    call    ?init@tobj1@@QAE_NXZ            ; tobj1::init
    test    al, al
    je    SHORT $L105190


Кроме того, если ты не будешь использовать bool, а нормальный int-based тип, то сравниваться будет eax, что обычно быстрее (т.к. команда другая).

Да, кстати, там у тебя еще одна ошибка — определение tobj использует int fake, а декларация — нет.

R>Это вполне реальный паттерн. Нет преобразования исключений. Исключений говорит о неудачности транзакции. Нет никаких частичных восстановлений и фаиловер. У меня лично такого кода очень много и я знаю, что и у других тоже. Я хочу мерить это.


Т.е. ты всегда выпускаешь все исключения наверх? Вообще, сколько я видел — обычно обрабатывают часть исключений на месте, дабы обеспечить реакцию (например, почему не завершена транзакция, не прочитан файл и т.п.), а затем в зависимости от действий пользователя продолжают выполнение.
В любом случае, то что у тебя — это лишь один из паттернов, и делать на только его основе какие-то выводы — по меньшей мере странно.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 09:20
Оценка:
R>з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.

Поэтому и надо ставить приоритет реалтайм и привязывать к одном процессору, как тут уже говорили. Еще и рабочую область неплохо бы закоммитить.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[7]: [Investigation] Exceptions vs. Return Values
От: rm822 Россия  
Дата: 03.04.07 09:28
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, rm822, Вы писали:


R>>Здравствуйте, remark, Вы писали:


R>>>Здравствуйте, rm822, Вы писали:


R>>>>>>Двойка вам за научный подход.


R>>>Тут основная проблема, что бы сделать тесты справедливые для обоих стратегий.

R>>>Т.е. что я делаю — беру некую предельно простую абстракцию — ресурс — приписываю ему семантику — его надо выделить, причём выделение может провалится, и его обязательно надо освободить при выходе из функции. Далее я моделирую эту абстракцию на С++ и на С предельно "честно" по отношению к обоим языкам и их возможностям — на С++ — объект с деструктором, на С — функции construct/destroy. И сравниваю именно эти реализации одной и той же задачи разными средствами. Какая реализация быстрее?
R>>>Сравнивать тёплое с мягким нет смысла.
R>>>Т.е. нет смысла мерить типа "а что если мы в с++ вставим дополнительный new/delete" — ты тогда и в С вставь тоже что-то, что будет решать ту задачу, для решения которой ты в С++ вставил дополнительный new/delete.
R>>>Т.е. ты придумай некую абстрактную задачу, которая бы на С++ требовала применения иерархий ошибок/динамического полиморфизма и т.д., потом максимально "честно" вырази её решение на С, причём там, что бы тебе потом не говорили — а я бы это сделал подругому и быстрее. И вот тогда будем мерить, где решение задачи "мега динамической полиморфной обработки ошибок" работает быстрее.

R>>Реальность такова что для обработки исключений используется иерахия классов а не int.(Обычно) Для обработки ошибок error-кодами используется int а не классы. (Обычно) И сравнивать нужно именно теплое с мягким, потому что такова реальность.


R>Обычно и не думают о наносекундах, и что?

Короче, мне этот пустой пи.... надоел — сам все проверю когда время будет

R>>>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[18]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 09:44
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

M>>>>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.


AS>>>Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?


M>>начать можно тут

M>>http://www.codenet.ru/progr/optimize/kk/

AS>Ничего не напоминает? А рассуждения о том, что минимальное время выполнения зависит только от программного окружения — очень и очень спорно. Особенно при наличии многопроцессорных и неюниформных юнитов.

AS>Кстати, там же и про RDTSC есть и про то, что и как он меряет. И почему то, что автора топика, неправильно. И читать это полезно как раз не мне (хотя мне это и интересно, впрочем, статью эту я уже читал), а автору топика и тестов...


Вот и он говорит, что можно брать и минимальное время тоже.
Тут зависит от того что мерить. Если мерить обращения к БД по сети, то возможно лечше брать некое среднее время. А если я хочу замерить время выполнения функции порядка десятков тактов, которая никак не связана ни со свопом, ни с памятью, ни с диском, ни с сетью и т.д., то самая оптимальная, т.к. "чистая", стратегия — это минимальное время. А уже все третьи задержки, будут одинаково добавляться что к одному времени, что к другому. Если будем мерить среднее в данном случае, то всё что получим — ненужную дисперсию.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 10:14
Оценка:
Здравствуйте, Andrew S, Вы писали:

R>>з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.


AS>Поэтому и надо ставить приоритет реалтайм и привязывать к одном процессору, как тут уже говорили. Еще и рабочую область неплохо бы закоммитить.


Если мерить длинный интервал и запускать функцию _один_ раз, то да. В моём случае всё это учтено, поэтому ничего этого не надо — это никак не повлияет на результат.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Ассемблер для Andrew S
От: CreatorCray  
Дата: 03.04.07 10:17
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....

если указывать __declspec(noinline) — то не будет гарантировано.
Впрочем вот:

test_ex
    PUBLIC ?test_ex@@YAXXZ
?test_ex@@YAXXZ    PROC NEAR
$B3$1:                          ; Preds $B3$0
;;; {
$LN118:
        push      ebp                                           ;29.1
        mov       ebp, esp                                      ;29.1
        push      -1                                            ;29.1
        push      OFFSET FLAT: B3$EH                            ;29.1
        mov       eax, DWORD PTR fs:__except_list               ;29.1
        push      eax                                           ;29.1
        mov       DWORD PTR fs:__except_list, esp               ;29.1
        sub       esp, 16                                       ;29.1
        mov       DWORD PTR [ebp-16], esp                       ;29.1
        mov       DWORD PTR [ebp-28], edi                       ;29.1
        mov       DWORD PTR [ebp-24], esi                       ;29.1
        mov       DWORD PTR [ebp-20], ebx                       ;29.1
                                ; LOE ebx esi edi bl bh
$B3$2:                          ; Preds $B3$1
$LN119:
;;;     tobj o1, o2, o3, o4;
        mov       DWORD PTR [ebp-4], 0                          ;30.7
                                ; LOE ebx esi edi bl bh
$B3$3:                          ; Preds $B3$2
$B3$4:                          ; Preds $B3$3
$LN120:
        mov       DWORD PTR [ebp-4], 1                          ;30.11
                                ; LOE ebx esi edi bl bh
$B3$5:                          ; Preds $B3$4
$B3$6:                          ; Preds $B3$5
$LN121:
        mov       DWORD PTR [ebp-4], 2                          ;30.15
                                ; LOE ebx esi edi bl bh
$B3$7:                          ; Preds $B3$6
$B3$8:                          ; Preds $B3$7
$LN122:
        mov       DWORD PTR [ebp-4], 3                          ;30.19
                                ; LOE ebx esi edi bl bh
$B3$9:                          ; Preds $B3$8
$LN123:
;;;     test_ex2();
        call      ?test_ex2@@YAXXZ                              ;31.2
                                ; LOE ebx esi edi bl bh
$B3$10:                         ; Preds $B3$9
$LN124:
;;;     test_ex2();
        call      ?test_ex2@@YAXXZ                              ;32.2
                                ; LOE ebx esi edi bl bh
$B3$11:                         ; Preds $B3$10
$LN125:
;;;     test_ex2();
        call      ?test_ex2@@YAXXZ                              ;33.2
                                ; LOE ebx esi edi bl bh
$B3$12:                         ; Preds $B3$11
$LN126:
;;;     test_ex2();
        call      ?test_ex2@@YAXXZ                              ;34.2
                                ; LOE ebx esi edi bl bh
$B3$13:                         ; Preds $B3$12
;;; }
$LN127:
        mov       ecx, DWORD PTR [ebp-12]                       ;35.1
        mov       DWORD PTR fs:__except_list, ecx               ;35.1
        mov       esp, ebp                                      ;35.1
        pop       ebp                                           ;35.1
        ret                                                     ;35.1
                                ; LOE
;?test_ex@@YAXXZ    ENDS
destr_detour28$0$130::
destr_detour29$0$130::
destr_detour30$0$130::
$B3$15:                         ; Preds $B3$7 $B3$5 $B3$3       ; Very Infreq
$LN128:
        ret                                                     ;30.11
                                ; LOE
destr_detour27$0$130::
$B3$21:                         ; Preds $B3$1                   ; Very Infreq
$LN129:
        ret                                                     ;30.7
        ALIGN     2
B3$EH::                                                         ;
        mov       eax, OFFSET FLAT: FI_?test_ex@@YAXXZ          ;30.7
        jmp       ___CxxFrameHandler                            ;30.7


test_ex2
    PUBLIC ?test_ex2@@YAXXZ
?test_ex2@@YAXXZ    PROC NEAR
$B5$1:                          ; Preds $B5$0
;;; {
$LN132:
        push      esi                                           ;24.1
$LN133:
;;;     if (!++counter) throw 0;
        mov       eax, DWORD PTR ?counter@@3HC                  ;25.9
        add       eax, 1                                        ;25.9
        mov       DWORD PTR ?counter@@3HC, eax                  ;25.9
$LN134:
        jne       $B5$3         ; Prob 78%                      ;25.2
                                ; LOE ebx ebp esi edi
$B5$2:                          ; Preds $B5$1
$LN135:
        mov       DWORD PTR [esp], 0                            ;25.18
        lea       eax, DWORD PTR [esp]                          ;25.18
$LN136:
        push      OFFSET FLAT: __TI1H                           ;25.24
        push      eax                                           ;25.24
        call      __CxxThrowException@8                         ;25.24
                                ; LOE ebx ebp esi edi
$B5$3:                          ; Preds $B5$2 $B5$1
;;; }
$LN137:
        pop       ecx                                           ;26.1
        ret                                                     ;26.1
        ALIGN     2
                                ; LOE
; mark_end;
?test_ex2@@YAXXZ ENDP


test_rv
    PUBLIC ?test_rv@@YA_NXZ
?test_rv@@YA_NXZ    PROC NEAR
$B3$1:                          ; Preds $B3$0
;;; {
$LN114:
$LN115:
;;;     int o1, o2, o3, o4;
;;;     bool res = true;
;;;     if (!ctor(&o1)) goto end;
;;;     if (!ctor(&o2)) goto do1;
;;;     if (!ctor(&o3)) goto do2;
;;;     if (!ctor(&o4)) goto do3;
;;;     if (!test_rv2()) goto do4;
        call      ?test_rv2@@YA_NXZ                             ;50.7
                                ; LOE eax ebx ebp esi edi
$B3$2:                          ; Preds $B3$1
        movzx     eax, al                                       ;50.7
$LN116:
        test      eax, eax                                      ;50.2
        je        $B3$8         ; Prob 78%                      ;50.2
                                ; LOE ebx ebp esi edi
$B3$3:                          ; Preds $B3$2
$LN117:
;;;     if (!test_rv2()) goto do4;
        call      ?test_rv2@@YA_NXZ                             ;51.7
                                ; LOE eax ebx ebp esi edi
$B3$4:                          ; Preds $B3$3
        movzx     eax, al                                       ;51.7
$LN118:
        test      eax, eax                                      ;51.2
        je        $B3$8         ; Prob 78%                      ;51.2
                                ; LOE ebx ebp esi edi
$B3$5:                          ; Preds $B3$4
$LN119:
;;;     if (!test_rv2()) goto do4;
        call      ?test_rv2@@YA_NXZ                             ;52.7
                                ; LOE eax ebx ebp esi edi
$B3$6:                          ; Preds $B3$5
        movzx     eax, al                                       ;52.7
$LN120:
        test      eax, eax                                      ;52.2
        je        $B3$8         ; Prob 78%                      ;52.2
                                ; LOE ebx ebp esi edi
$B3$7:                          ; Preds $B3$6
$LN121:
;;;     if (!test_rv2()) goto do4;
        call      ?test_rv2@@YA_NXZ                             ;53.7
                                ; LOE ebx ebp esi edi
$B3$8:                          ; Preds $B3$7 $B3$6 $B3$4 $B3$2
$LN122:
;;;     res = true;
;;; do4:    dtor(&o4);
;;; do3:    dtor(&o3);
;;; do2:    dtor(&o2);
;;; do1:    dtor(&o1);
;;; end:    return res;
        mov       eax, 1                                        ;59.16
        ret                                                     ;59.16
        ALIGN     2


test_rv2
    PUBLIC ?test_rv2@@YA_NXZ
?test_rv2@@YA_NXZ    PROC NEAR
$B5$1:                          ; Preds $B5$0
;;; {
$LN125:
$LN126:
;;;     return !!++counter;
        mov       edx, DWORD PTR ?counter@@3HC                  ;39.13
        add       edx, 1                                        ;39.13
        mov       DWORD PTR ?counter@@3HC, edx                  ;39.13
        mov       eax, 0                                        ;39.13
        mov       ecx, 1                                        ;39.13
        cmovne    eax, ecx                                      ;39.13
        ret                                                     ;39.13
        ALIGN     2
                                ; LOE
; mark_end;
?test_rv2@@YA_NXZ ENDP
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 10:28
Оценка:
AS>>А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....
CC>если указывать __declspec(noinline) — то не будет гарантировано.
CC>Впрочем вот:

Cудя по коду для rv, icc убрал вызовы ctor и dtor. Мы договорились этого не делать
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 10:29
Оценка:
R>>>з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.

AS>>Поэтому и надо ставить приоритет реалтайм и привязывать к одном процессору, как тут уже говорили. Еще и рабочую область неплохо бы закоммитить.


R>Если мерить длинный интервал и запускать функцию _один_ раз, то да. В моём случае всё это учтено, поэтому ничего этого не надо — это никак не повлияет на результат.


Ладно, ладно, мы все тупые, а ты один умный. Делай как знаешь
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[19]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 10:35
Оценка: +1
M>>>>>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.

AS>>>>Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?


M>>>начать можно тут

M>>>http://www.codenet.ru/progr/optimize/kk/

AS>>Ничего не напоминает? А рассуждения о том, что минимальное время выполнения зависит только от программного окружения — очень и очень спорно. Особенно при наличии многопроцессорных и неюниформных юнитов.

AS>>Кстати, там же и про RDTSC есть и про то, что и как он меряет. И почему то, что автора топика, неправильно. И читать это полезно как раз не мне (хотя мне это и интересно, впрочем, статью эту я уже читал), а автору топика и тестов...

R>Вот и он говорит, что можно брать и минимальное время тоже.


Когда он это говорил, про мультиядерность, доступную обычному юзеру, еще не было и речи. Соответственно, не было речи и про NUMA, про синхронизации кешей и прочие вещи, характерные для многопроцессорных систем. Минимальное время выполнения там зависит от аппаратных компонент, на которых по прихоти шедуллера будет выполняться код. Правда, там есть упоминания о беспричинных выпадениях для K7 и KT133. Поэтому выпадения минимума могут быть _НАСТОЛЬКО_ редки и нехарактерны, что ты можешь с приличной вероятностью получить fake (даже программно — например, для одного варианта шедулер может всегда выбирать один юнит, а для другого — например, всегда другой). Гарантировать ты это в твоей реализации не сможешь. Поэтому и надо:
1. Привязывать к юниту.
2. Поднимать приоритеты.
3. Брать средне-минимальное время.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[7]: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 10:43
Оценка:
Здравствуйте, Andrew S, Вы писали:

R>>>>з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.


AS>>>Поэтому и надо ставить приоритет реалтайм и привязывать к одном процессору, как тут уже говорили. Еще и рабочую область неплохо бы закоммитить.


R>>Если мерить длинный интервал и запускать функцию _один_ раз, то да. В моём случае всё это учтено, поэтому ничего этого не надо — это никак не повлияет на результат.


AS>Ладно, ладно, мы все тупые, а ты один умный. Делай как знаешь


Сейчас сколько бы раз я не запускал тест у меня получается, допустим 172.
Т.е. ты хочешь сказать, если я запущу свой тест на своей машине с привязкой к ядру, с установкой максимального приоритета, коммитом памяти и т.д., у меня выдастся другое число?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [Investigation] Exceptions vs. Return Values
От: Erop Россия  
Дата: 03.04.07 10:45
Оценка:
Здравствуйте, remark, Вы писали:

R>Что я понял уже когда я это всё доделал, что надо было код не кустарным способом делать, а сделать генератор кода, которому задаёшь параметр — кол-во "ресурсов, кол-во уровней вызовов и т.д. и что бы он генерировал много красивого кода. И снабдить это ещё скриптами для автоматической сборки и что бы результаты выводились сразу в виде красивых табличек. Тогда бы я это выложил и все желающие запускали бы это на своих платформах и потом выкладывали бы сюда свои результаты... тогда и для ARM'ов бы можно было протестировать и более точно проследить зависимости скорости/размера кода от различных параметров типа кол-ва "ресурсов".


R>К сожалению это не ко мне. Может руки дойдут это оформить в виде набора файлов, который можно запустить на своей платформе и выложить результаты...


Ну ты, например, можешь выложить то, что есть, а руки могут дойти у кого-то ещё
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 10:46
Оценка:
R>>>>>з.ы. а мерить среднее время всё-таки некорректно, если ты запустишь тест несколько раз, то увидишь, что время "плавает", т.е. сказываются третьи факторы, с минимальным временем такого нет.

AS>>>>Поэтому и надо ставить приоритет реалтайм и привязывать к одном процессору, как тут уже говорили. Еще и рабочую область неплохо бы закоммитить.


R>>>Если мерить длинный интервал и запускать функцию _один_ раз, то да. В моём случае всё это учтено, поэтому ничего этого не надо — это никак не повлияет на результат.


AS>>Ладно, ладно, мы все тупые, а ты один умный. Делай как знаешь


R>Сейчас сколько бы раз я не запускал тест у меня получается, допустим 172.

R>Т.е. ты хочешь сказать, если я запущу свой тест на своей машине с привязкой к ядру, с установкой максимального приоритета, коммитом памяти и т.д., у меня выдастся другое число?

Вполне вероятно. Особенно если ты увеличишь количество итераций. Привязка к ядру — но ты же не только на своей машине планируешь запускать тест, ведь так?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: Ассемблер для Andrew S
От: CreatorCray  
Дата: 03.04.07 11:15
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....

CC>>если указывать __declspec(noinline) — то не будет гарантировано.
CC>>Впрочем вот:

AS>Cудя по коду для rv, icc убрал вызовы ctor и dtor. Мы договорились этого не делать

Увы, заставить его не убирать совершенно пустые функции не получается... Щас проведу эксперимент — добавлю _asm nop в них
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 11:18
Оценка:
AS>>>>А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....
CC>>>если указывать __declspec(noinline) — то не будет гарантировано.
CC>>>Впрочем вот:

AS>>Cудя по коду для rv, icc убрал вызовы ctor и dtor. Мы договорились этого не делать

CC>Увы, заставить его не убирать совершенно пустые функции не получается... Щас проведу эксперимент — добавлю _asm nop в них

Используй тот код, что приводил я (c init\release). В этом случае не должно убрать — если только линкер не оптимизирует.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: Ассемблер для Andrew S
От: CreatorCray  
Дата: 03.04.07 11:45
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>>>А можете привести листинги для функций? Вдруг ic там что проинлайнил? Он может....

CC>>>>если указывать __declspec(noinline) — то не будет гарантировано.
CC>>>>Впрочем вот:

AS>>>Cудя по коду для rv, icc убрал вызовы ctor и dtor. Мы договорились этого не делать

CC>>Увы, заставить его не убирать совершенно пустые функции не получается... Щас проведу эксперимент — добавлю _asm nop в них

AS>Используй тот код, что приводил я (c init\release). В этом случае не должно убрать — если только линкер не оптимизирует.

Кинь ссылкой плз, бо в этом топике уже черт ногу сломит.
Скомпилил с nop-ами — получилось одинаково у обоих — 182
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 12:13
Оценка:
AS>>Используй тот код, что приводил я (c init\release). В этом случае не должно убрать — если только линкер не оптимизирует.
CC>Кинь ссылкой плз, бо в этом топике уже черт ногу сломит.

http://www.rsdn.ru/Forum/Message.aspx?mid=2430252&amp;only=1
Автор: Andrew S
Дата: 03.04.07

В конце сообщения.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[7]: Ассемблер для Andrew S
От: minorlogic Украина  
Дата: 03.04.07 12:13
Оценка: -2
Здравствуйте, Andrew S, Вы писали:

AS>Ладно, ладно, мы все тупые, а ты один умный. Делай как знаешь


Должен заметить, что полезную информацию дал пока что только Ремарк. От вас , кроме НЕконструктивной критики пока не было ничего.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[8]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 12:19
Оценка: -1
AS>>Ладно, ладно, мы все тупые, а ты один умный. Делай как знаешь

M>Должен заметить, что полезную информацию дал пока что только Ремарк. От вас , кроме НЕконструктивной критики пока не было ничего.


А от вас пока ничего, кроме флуда (хотя нет, была ссылка на статью про книгу криса касперски, и то не по адресу). Есть что по делу то сказать?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[10]: Ассемблер для Andrew S
От: CreatorCray  
Дата: 03.04.07 12:54
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>>>Используй тот код, что приводил я (c init\release). В этом случае не должно убрать — если только линкер не оптимизирует.

CC>>Кинь ссылкой плз, бо в этом топике уже черт ногу сломит.

AS>http://www.rsdn.ru/Forum/Message.aspx?mid=2430252&amp;only=1
Автор: Andrew S
Дата: 03.04.07

Пасиб
правда все равно пришлось nop и __declspec(noinline) вставить...

test_ex: 180
test_rv: 180



?test_rv@@YA_NXZ    PROC NEAR PRIVATE
$B3$1:                          ; Preds $B3$0
;;; {
$LN119:
        push      ebp                                           ;67.1
        sub       esp, 16                                       ;67.1
$LN120:
;;;     tobj1 o1, o2, o3, o4;
;;;     bool res = false;
;;;     if (o1.init())
        lea       ecx, DWORD PTR [esp+12]                       ;70.9
        call      ?init@tobj1@@QAEHXZ                           ;70.9
                                ; LOE eax ebx esi edi
$B3$2:                          ; Preds $B3$1
$LN121:
        test      eax, eax                                      ;70.2
        jne       $B3$5         ; Prob 5%                       ;70.2
                                ; LOE ebx esi edi
$B3$3:                          ; Preds $B3$2
        xor       ebp, ebp                                      ;
                                ; LOE ebx ebp esi edi
$B3$4:                          ; Preds $B3$8 $B3$3
$LN122:
;;;     {
;;;         if (o2.init())
;;;         {
;;;             if (o3.init())
;;;             {
;;;                 if (o4.init())
;;;                 {
;;;                     res = test_rv2() && test_rv2() && test_rv2() && test_rv2();
;;;                     o4.release();
;;;                 }
;;;                 o3.release();
;;;             }
;;;             o2.release();
;;;         }
;;;         o1.release();
;;;     }
;;;     return res;
        mov       eax, ebp                                      ;87.9
        add       esp, 16                                       ;87.9
        pop       ebp                                           ;87.9
        ret                                                     ;87.9
                                ; LOE
$B3$5:                          ; Preds $B3$2                   ; Infreq
$LN123:
        lea       ecx, DWORD PTR [esp+8]                        ;72.10
        call      ?init@tobj1@@QAEHXZ                           ;72.10
                                ; LOE eax ebx esi edi
$B3$6:                          ; Preds $B3$5                   ; Infreq
$LN124:
        test      eax, eax                                      ;72.3
        jne       $B3$9         ; Prob 5%                       ;72.3
                                ; LOE ebx esi edi
$B3$7:                          ; Preds $B3$6                   ; Infreq
        xor       ebp, ebp                                      ;
                                ; LOE ebx ebp esi edi
$B3$8:                          ; Preds $B3$12 $B3$7            ; Infreq
$LN125:
        lea       ecx, DWORD PTR [esp+12]                       ;85.6
        call      ?release@tobj1@@QAEXXZ                        ;85.6
        jmp       $B3$4         ; Prob 100%                     ;85.6
                                ; LOE ebx ebp esi edi
$B3$9:                          ; Preds $B3$6                   ; Infreq
$LN126:
        lea       ecx, DWORD PTR [esp+4]                        ;74.11
        call      ?init@tobj1@@QAEHXZ                           ;74.11
                                ; LOE eax ebx esi edi
$B3$10:                         ; Preds $B3$9                   ; Infreq
$LN127:
        test      eax, eax                                      ;74.4
        jne       $B3$13        ; Prob 5%                       ;74.4
                                ; LOE ebx esi edi
$B3$11:                         ; Preds $B3$10                  ; Infreq
        xor       ebp, ebp                                      ;
                                ; LOE ebx ebp esi edi
$B3$12:                         ; Preds $B3$26 $B3$11           ; Infreq
$LN128:
        lea       ecx, DWORD PTR [esp+8]                        ;83.7
        call      ?release@tobj1@@QAEXXZ                        ;83.7
        jmp       $B3$8         ; Prob 100%                     ;83.7
                                ; LOE ebx ebp esi edi
$B3$13:                         ; Preds $B3$10                  ; Infreq
$LN129:
        lea       ecx, DWORD PTR [esp]                          ;76.12
        call      ?init@tobj1@@QAEHXZ                           ;76.12
                                ; LOE eax ebx esi edi
$B3$14:                         ; Preds $B3$13                  ; Infreq
$LN130:
        test      eax, eax                                      ;76.5
        jne       $B3$16        ; Prob 22%                      ;76.5
                                ; LOE ebx esi edi
$B3$15:                         ; Preds $B3$14                  ; Infreq
        xor       ebp, ebp                                      ;
        jmp       $B3$26        ; Prob 100%                     ;
                                ; LOE ebx ebp esi edi
$B3$16:                         ; Preds $B3$14                  ; Infreq
$LN131:
        call      ?test_rv2@@YAHXZ                              ;78.12
                                ; LOE eax ebx esi edi
$B3$17:                         ; Preds $B3$16                  ; Infreq
        test      eax, eax                                      ;78.12
        je        $B3$22        ; Prob 78%                      ;78.12
                                ; LOE ebx esi edi
$B3$18:                         ; Preds $B3$17                  ; Infreq
$LN132:
        call      ?test_rv2@@YAHXZ                              ;78.26
                                ; LOE eax ebx esi edi
$B3$19:                         ; Preds $B3$18                  ; Infreq
        test      eax, eax                                      ;78.26
        je        $B3$22        ; Prob 78%                      ;78.26
                                ; LOE ebx esi edi
$B3$20:                         ; Preds $B3$19                  ; Infreq
$LN133:
        call      ?test_rv2@@YAHXZ                              ;78.40
                                ; LOE eax ebx esi edi
$B3$21:                         ; Preds $B3$20                  ; Infreq
        test      eax, eax                                      ;78.40
        jne       $B3$23        ; Prob 22%                      ;78.40
                                ; LOE ebx esi edi
$B3$22:                         ; Preds $B3$19 $B3$17 $B3$21    ; Infreq
$LN134:
        xor       ebp, ebp                                      ;78.6
        jmp       $B3$25        ; Prob 100%                     ;78.6
                                ; LOE ebx ebp esi edi
$B3$23:                         ; Preds $B3$21                  ; Infreq
$LN135:
        call      ?test_rv2@@YAHXZ                              ;78.54
                                ; LOE eax ebx esi edi
$B3$24:                         ; Preds $B3$23                  ; Infreq
        mov       edx, 1                                        ;78.54
        cmp       eax, 0                                        ;78.54
        mov       ebp, 0                                        ;78.54
        cmovne    ebp, edx                                      ;78.54
                                ; LOE ebx ebp esi edi
$B3$25:                         ; Preds $B3$24 $B3$22           ; Infreq
$LN136:
        lea       ecx, DWORD PTR [esp]                          ;79.9
        call      ?release@tobj1@@QAEXXZ                        ;79.9
                                ; LOE ebx ebp esi edi
$B3$26:                         ; Preds $B3$25 $B3$15           ; Infreq
$LN137:
        lea       ecx, DWORD PTR [esp+4]                        ;81.8
        call      ?release@tobj1@@QAEXXZ                        ;81.8
        jmp       $B3$12        ; Prob 100%                     ;81.8


?test_rv2@@YAHXZ    PROC NEAR
$B5$1:                          ; Preds $B5$0
;;; {
$LN141:
$LN142:
;;;     return (!!++counter);
        mov       edx, DWORD PTR ?counter@@3HC                  ;46.14
        add       edx, 1                                        ;46.14
        mov       DWORD PTR ?counter@@3HC, edx                  ;46.14
        mov       eax, 0                                        ;46.14
        mov       ecx, 1                                        ;46.14
        cmovne    eax, ecx                                      ;46.14
        ret                                                     ;46.14


?release@tobj1@@QAEXXZ    PROC NEAR
; parameter 1(this): ecx
$B4$1:                          ; Preds $B4$0
;;; {
                                ; LOE ebx ebp esi edi
$B4$5:                          ; Preds $B4$1
; Begin ASM
$LN138:
$LN139:
;;;     _asm nop;
        nop                                                     ;63.7
; End ASM
                                ; LOE ebx ebp esi edi
$B4$2:                          ; Preds $B4$5
;;; }
$LN140:
        ret                                                     ;64.1

?init@tobj1@@QAEHXZ    PROC NEAR
; parameter 1(this): ecx
$B40$1:                         ; Preds $B40$0
                                ; LOE ebx ebp esi edi
$B40$5:                         ; Preds $B40$1
; Begin ASM
$LN1042:
$LN1043:
        nop                                                     ;58.7
; End ASM
                                ; LOE ebx ebp esi edi
$B40$2:                         ; Preds $B40$5
$LN1044:
        mov       eax, 1                                        ;59.9
        ret                                                     ;59.9
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: Programador  
Дата: 03.04.07 13:54
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, <Аноним>, Вы писали:


А>>1 — передача адреса без чтония памяти. la заместо mov


GN>Имеется ввиду команда lea? Не пойму, как она может быть лучше.



А>>2 — Может E(ABCD)X кончильсь, а указатели остались.


GN>Указатели, как и данные, могут храниться в любом регистре.


Хранение данных в индексных регистрах несколько ограничивает возможные операции, хоть бывает это оправдано. Насчет lea я имел ввиду случай когда можно получить адрес а переменная прямо сейчас не понадобится или например может вообще не понадобится в зависимости от условий. Lea использует например this, который в регистре и константный офсет а реального чтения не происходит изза значений флагов.

В приведенных кодах некоторое сомнение вызывает сочетание __declspec и __fastcall

Кстати тут недавно кто-то volatile использовал для борьбы с компилятором
Re[5]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 03.04.07 14:38
Оценка:
Здравствуйте, Programador, Вы писали:

P>В приведенных кодах некоторое сомнение вызывает сочетание __declspec и __fastcall

Чем?
__declspec(noinline) запрещает компилеру инлайнинг данной функции
__fastcall грит компилеру чтоб старался передавать параметры через регистры

все для чего это тут надо — чтоб компилер не выкидывал пустые функции а тратил на их вызов тики
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 03.04.07 14:53
Оценка: -1
Здравствуйте, Andrew S, Вы писали:

R>>Сейчас сколько бы раз я не запускал тест у меня получается, допустим 172.

R>>Т.е. ты хочешь сказать, если я запущу свой тест на своей машине с привязкой к ядру, с установкой максимального приоритета, коммитом памяти и т.д., у меня выдастся другое число?

AS>Вполне вероятно. Особенно если ты увеличишь количество итераций.


Интересно за счёт чего? И ты ещё говорил о компетентности

AS>Привязка к ядру — но ты же не только на своей машине планируешь запускать тест, ведь так?


При чём тут, что я планирую. Я запускал на однопроцессорной машине. Если я запланирую запускать ещё где-то, то тогда я возможно запланирую и изменить методику измерения, если это будет нужно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 15:12
Оценка: -1
R>>>Сейчас сколько бы раз я не запускал тест у меня получается, допустим 172.
R>>>Т.е. ты хочешь сказать, если я запущу свой тест на своей машине с привязкой к ядру, с установкой максимального приоритета, коммитом памяти и т.д., у меня выдастся другое число?

AS>>Вполне вероятно. Особенно если ты увеличишь количество итераций.


R>Интересно за счёт чего? И ты ещё говорил о компетентности


За счет того, что шедуллер будет выделять больше времени твоему потоку. Или ты думаешь, в системе один поток и он твой?
Это во-первых. А во-вторых, о компетентности прямо я не говорил (хотя и советовал тебе ознакомиться хотя бы со статьей, приведенной в топике), но теперь могу наверное и начать

AS>>Привязка к ядру — но ты же не только на своей машине планируешь запускать тест, ведь так?


R>При чём тут, что я планирую. Я запускал на однопроцессорной машине. Если я запланирую запускать ещё где-то, то тогда я возможно запланирую и изменить методику измерения, если это будет нужно.


Ууу.. все ясно. Ок, уговорил — больше в таком "интересном" варианте мне общаться не хочется. Конструктива с твоей стороны я не вижу, хотя привел уже несколько ошибок в твоем тесте, ты, похоже, считаешь, что все в порядке. На критику ты реагируешь тоже весьма "интересно". В общем, желаю удачи и доработать тесты хотя бы до вменяемого состояния
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: [Investigation] Exceptions vs. Return Values
От: Programador  
Дата: 03.04.07 15:34
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, Programador, Вы писали:


P>>В приведенных кодах некоторое сомнение вызывает сочетание __declspec и __fastcall

CC>Чем?
CC>__declspec(noinline) запрещает компилеру инлайнинг данной функции
CC>__fastcall грит компилеру чтоб старался передавать параметры через регистры

CC>все для чего это тут надо — чтоб компилер не выкидывал пустые функции а тратил на их вызов тики


там был импортный __declspec и у него баг случился — при оптимизации параметры в стек засунулись, а не в регистры.

У меня такое отношение что __fastcall это типа инлайне. Хотя в принципе экспорт можно подружить с инлайне путем дублирования кода
Re[7]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 03.04.07 15:48
Оценка: +1
P>У меня такое отношение что __fastcall это типа инлайне. Хотя в принципе экспорт можно подружить с инлайне путем дублирования кода

Отчего ж? Из кернела экспортируются функции с конвенцией fastcall — и ничего, все работает Фасткалл — это конвенция вызова и ничего более — к экспорту\импорту она не должна иметь отношения, кроме как для манглинга...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 01:34
Оценка:
Здравствуйте, Programador, Вы писали:

P>Хранение данных в индексных регистрах несколько ограничивает возможные операции, хоть бывает это оправдано.


В x86-32 нет индексных регистров, все равноправны.

P>Насчет lea я имел ввиду случай когда можно получить адрес а переменная прямо сейчас не понадобится или например может вообще не понадобится в зависимости от условий. Lea использует например this, который в регистре и константный офсет а реального чтения не происходит изза значений флагов.


Если чтения нет — компилятор не справился с оптимизацией, сгенерировав лишние команды. Если чтение есть — нет разницы в скорости.

Компилятор для ссылки довольно часто может обойтись вообще compile-time вычислениями, не генерируя код, но делает так не всегда.

P>В приведенных кодах некоторое сомнение вызывает сочетание __declspec и __fastcall


Это правильно, поскольку функция экспортируется именно так.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 01:34
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну под дебагом-то что код смотреть?


Баги кодогенератора проявились в дебаге, в релизе просто повезло в конкретном случае.

R>Ты приведи пример, где под релизом так.


На коде небольшого размера не получается воспроизвести, а оставить как есть в продакшене и потом ждать багрепорты об ошибке 2го порядка довольно накладно.

R>В msvc помогает "добить" такие места, где не идельная оптимизация, включение link-time code generation — он как раз вот такие "форварды" должен элиминировать.


Я проводил довольно простой тест — сначала заинклудил все cpp в основной и скомпелировал, потом компелировал по-раздельности и линковал с /LTCG — в последнем случае код хуже.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 01:46
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну так исключение всё равно может полететь, и деструкторы есть, значит фрейм всё равно надо устанавливать.


Тем более, эти результаты неверны, это уже с++/rv+ex какой-то.

R>>>А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.


GN>>Не верю Компилятор там один и тот же.


R>В С — там код более явный, поэтому у компилятора меньше свободы, а в С++ менее явный — и у компилятора больше свободы.


Интересная теория, я всегда считал что С и С++ перед оптимизацией трансформируется в одно и тоже ADT.

R>Я глядел сгенерированный код "с++/rv" — я там даже сразу не понял, что он там к чему нагенерил — там он как-то хитро пишет прям в стек, т.е. не push/pop, а mov [sp],x и всякого такого рода вещи.


При оптимизации по скорости так происходит довольно часто.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[6]: [Investigation] Exceptions vs. Return Values
От: Programador  
Дата: 04.04.07 08:45
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, Programador, Вы писали:


P>>Хранение данных в индексных регистрах несколько ограничивает возможные операции, хоть бывает это оправдано.


GN>В x86-32 нет индексных регистров, все равноправны.


Равноправны 2 регистра FS и GS это совсем не все


P>>Насчет lea я имел ввиду случай когда можно получить адрес а переменная прямо сейчас не понадобится или например может вообще не понадобится в зависимости от условий. Lea использует например this, который в регистре и константный офсет а реального чтения не происходит изза значений флагов.


GN>Если чтения нет — компилятор не справился с оптимизацией, сгенерировав лишние команды. Если чтение есть — нет разницы в скорости.


GN>Компилятор для ссылки довольно часто может обойтись вообще compile-time вычислениями, не генерируя код, но делает так не всегда.

Я про рунтайм условия. Мы загружаем адрес, а память возможно не читаем, засчет этого ссылка на инт может быть быстрее
Re[7]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 09:23
Оценка:
Здравствуйте, Programador, Вы писали:

P>Равноправны 2 регистра FS и GS это совсем не все


Если говорить о сегментных регистрах, то FS и GS далеко не одно и тоже. Но для С++ это не имеет значения, поскольку в Виндовсе плоская модель памяти, компилятор использует только регистры общего назначения (eax, ecx, edx, ebx, ebp, esi, edi; esp традиционно используется как указатель стека).

P>Я про рунтайм условия. Мы загружаем адрес, а память возможно не читаем, засчет этого ссылка на инт может быть быстрее


Зачем загружать адрес, если в дальнейшем не будет чтения? Это лишние действия, т.е. код не оптимален.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 04.04.07 09:32
Оценка: +1
Здравствуйте, gear nuke, Вы писали:

GN>Если говорить о сегментных регистрах, то FS и GS далеко не одно и тоже. Но для С++ это не имеет значения, поскольку в Виндовсе плоская модель памяти, компилятор использует только регистры общего назначения (eax, ecx, edx, ebx, ebp, esi, edi; esp традиционно используется как указатель стека).

Еще активно используется FS для thread-specific штук типа TLS и исключений
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: [Investigation] Exceptions vs. Return Values
От: Programador  
Дата: 04.04.07 12:50
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, Programador, Вы писали:


P>>Равноправны 2 регистра FS и GS это совсем не все


GN>Если говорить о сегментных регистрах, то FS и GS далеко не одно и тоже. Но для С++ это не имеет значения, поскольку в Виндовсе плоская модель памяти, компилятор использует только регистры общего назначения (eax, ecx, edx, ebx, ebp, esi, edi; esp традиционно используется как указатель стека).


И что нет каких либо названий для первых четырех?
Потом говорить esp указатель стека просто по традиции не совсем корректно. Кстати вопрос — заметил что возможна адресация [esp+ofset] , чего мне кажется в 486 не было. Вроде ebp уже не актуален, тоесть можно пользовать esp, учитывай только что он меняется по мере проталкивания параметров. Тогда дополнительный свободный регистр появляется?


P>>Я про рунтайм условия. Мы загружаем адрес, а память возможно не читаем, засчет этого ссылка на инт может быть быстрее


GN>Зачем загружать адрес, если в дальнейшем не будет чтения? Это лишние действия, т.е. код не оптимален.


Я про
int fun(int &a,int &b)
{  extern int c;
   return c?a:b;
}

и
int fun(int  a,int  b)
{  extern int c;
   return c?a:b;
}
Re[9]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 04.04.07 14:27
Оценка:
Здравствуйте, Programador, Вы писали:

P>Я про

P>
P>int fun(int &a,int &b)
P>{  extern int c;
P>   return c?a:b;
P>}
P>

P>и
P>
P>int fun(int  a,int  b)
P>{  extern int c;
P>   return c?a:b;
P>}
P>


Если у тя к моменту вызова этой функции ее аргументы будут в регистрах а сама функция не заинлайнится то получится только потеря производительности.

Вообще тут уже ИМХО экономия на спичках...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 04.04.07 18:54
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну ты, например, можешь выложить то, что есть, а руки могут дойти у кого-то ещё


Нет смысла выкладывать — если это делать, то проще с нуля.
Больше времени потратишь, если будешь адаптировать мой код.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 04.04.07 18:59
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, remark, Вы писали:


R>>Ну так исключение всё равно может полететь, и деструкторы есть, значит фрейм всё равно надо устанавливать.


GN>Тем более, эти результаты неверны, это уже с++/rv+ex какой-то.


Почему не верны?
Для "чистого" случая я мерял С-код там ничего такого не было — если тебе нужен такой случай, то бери эти результаты.
А тут я намеренно мерил "с++/rv+ex" — т.к. это есть реальный паттерн — некоторые библиотеки используют именно а таком виде, например, ACE.


R>>>>А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.


GN>>>Не верю Компилятор там один и тот же.


R>>В С — там код более явный, поэтому у компилятора меньше свободы, а в С++ менее явный — и у компилятора больше свободы.


GN>Интересная теория, я всегда считал что С и С++ перед оптимизацией трансформируется в одно и тоже ADT.


Я просто верб своим глазам, а машинный код говорит именно это...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 23:06
Оценка:
Здравствуйте, Programador, Вы писали:

P>И что нет каких либо названий для первых четырех?


Были, и для других то же, в 16ти битных процессорах.

P>Потом говорить esp указатель стека просто по традиции не совсем корректно. Кстати вопрос — заметил что возможна адресация [esp+ofset] , чего мне кажется в 486 не было.


В 16ти битном режиме нельзя было адресовать стек через sp.

P>Вроде ebp уже не актуален, тоесть можно пользовать esp, учитывай только что он меняется по мере проталкивания параметров. Тогда дополнительный свободный регистр появляется?


Andrew S писал тут про это не один раз. В случае ипользования исключений ebp занят под указатель на стековый кадр, иначе свободен.

P>>>Я про рунтайм условия. Мы загружаем адрес, а память возможно не читаем, засчет этого ссылка на инт может быть быстрее


GN>>Зачем загружать адрес, если в дальнейшем не будет чтения? Это лишние действия, т.е. код не оптимален.


P>Я про

P>
P>int fun(int &a,int &b)
P>{  extern int c;
P>   return c?a:b;
P>}
P>

P>и
P>
P>int fun(int  a,int  b)
P>{  extern int c;
P>   return c?a:b;
P>}

Во-первых, пример надуман, в реальном мире такого не будет (без const)
Во-вторых, поскольку размер int не больше, чем const int*, компилятору незачем использовать указатели, в лучшем случае код будет одинаков, в худьшем будут лишние копирования новых переменных (int a,int b).
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[7]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 04.04.07 23:06
Оценка:
Здравствуйте, remark, Вы писали:

R>Почему не верны?


Потому что написано с++/rv, а там с++/rv+ex (кстати, было и "там инструкции и на проверки возвращаемых значений и на поддержку исключений", но таблица сбила с толку )

R>Для "чистого" случая я мерял С-код там ничего такого не было — если тебе нужен такой случай, то бери эти результаты.


А, ну тогда практика согласуется с теорией — размер кода с исключениями не меньше, плюс еще размер неучтённых дополнительных данных.

R>Я просто верб своим глазам, а машинный код говорит именно это...


Я конечно соглашусь, что по машинному коду можно сказать: "вот это написано на С++". Потому что RAII, ООП и т.п. дают отпечаток даже () на исходном коде (как правило машинный код в этом случае не лучший). Но нельзя сказать уверенно: "это написано на С". Может быть и на С++. Никто же не запретит писать на С++ (практически) как на С. Когда активно используют расширенные возмоности — это видно. Например, по лишнему коду можно отличить std::auto_ptr от голого указателя, автоматические вызовы *структоров в new и delete от "эмуляции" их на С. Хотя на С++ можно получить более компактный результат, поскольку проще оптимизировать на более высоком уровне. А вот лушчего машинного кода у С++ я не только никогда не видел, но даже не могу понять, как большая свобода компилятора этому может способствовать
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[9]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 05.04.07 04:07
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Еще активно используется FS для thread-specific штук типа TLS и исключений


Не только для этого, но в сгенерированном из чистого С++ коде сегментных регистров не будет.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re: [Investigation] Exceptions vs. Return Values
От: c-smile Канада http://terrainformatica.com
Дата: 05.04.07 05:41
Оценка: :)
Здравствуйте, remark, Вы писали:

R>

smart_ptr vs. smart_ptr&

R>Попутно я исследовал следующий вопрос – имеет ли смысл передавать умные указатели по ссылке вместо передачи по значению. Мы зачастую (ну я по-крайней мере ) передаю просто boost::shared_ptr без ссылок – по значению.
R>Функции аналогичные функциям из предыдущего теста – просто много форвардинга вызовов функций, без выделения ресурсов, но при этом между функцими передавался один boost::intrusive_ptr, в одном случае по значению, в другом по ссылке.

А зачем вообще передавать boost::intrusive_ptr<T> через параметры?

Что дает применение:

void foo( const boost::intrusive_ptr<T>& ptr )

по сравнению с
void foo( const boost::intrusive_ptr<T>& ptr )


Может я чего не понимаю но
boost::intrusive_ptr<T> это средство memory management — т.е. при чем здесь параметры?
Re[2]: [Investigation] Exceptions vs. Return Values
От: c-smile Канада http://terrainformatica.com
Дата: 05.04.07 05:43
Оценка:
Здравствуйте, c-smile, Вы писали:

Поправка:

Что дает применение:

void foo( const boost::intrusive_ptr<T>& ptr )

по сравнению с
void foo( const T* ptr )


Может я чего не понимаю но
boost::intrusive_ptr<T> это средство memory management — т.е. при чем здесь параметры?
Re[10]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 05.04.07 06:23
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>но в сгенерированном из чистого С++ коде сегментных регистров не будет.

можно ли считать это чистым С++ кодом?
void foo()
{
 try
 {
  bar();
 }
 catch (...)
 {
  bar2();
 }
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 05.04.07 06:47
Оценка:
Возможно имелся ввиду shared_ptr ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[11]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 05.04.07 11:00
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>можно ли считать это чистым С++ кодом?

CC>
CC>void foo()
CC>{
CC> try
CC> {
CC>  bar();
CC> }
CC> catch (...)
CC> {
CC>  bar2();
CC> }
CC>}

Так и знал Это можно скомпелирвать g++ Формально я конечно не прав и MSVC использует FS (раз уж есть в ОС готовый механизм SEH). В этих случаях необходимость использования FS явно следует из контекста, его не нужно передавать в параметрах функции (как часть указателя). Говоря о плоской модели я всего лишь имел ввиду, что нет разницы, что адресует указатель — стек, хип, секцию данных исполняемого файла, даже адрес TIB — он всегда может храниться в любом из регистров общего назначения. (я бы лучше вместо fs вспомнил про eip, вот что действительно постоянно используется и является строго указателем )
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[12]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 05.04.07 11:34
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Так и знал

Любопытно, что именно знал?
GN> Формально я конечно не прав и MSVC использует FS
Я бы сказал "в общем случае не прав".
Да и фраза "но в сгенерированном из чистого С++ коде сегментных регистров не будет" звучит так, как будто любой С++ код будучи откомпилирован не будет содержать сегментных регистров.

А во всем остальном —
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[13]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 05.04.07 12:16
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Любопытно, что именно знал?


Что увижу этот пример

GN>> Формально я конечно не прав и MSVC использует FS

CC>Я бы сказал "в общем случае не прав".
CC>Да и фраза "но в сгенерированном из чистого С++ коде сегментных регистров не будет" звучит так, как будто любой С++ код будучи откомпилирован не будет содержать сегментных регистров.

Дык там я до этого писал "поскольку в Виндовсе плоская модель памяти" и далее продолжал в этом контексте. Если правильно понимаю, кастить к интегральному типу указатель в DOS — то сегментный регистр будет "добавлен" в результат, и наоборот; я имел ввиду, что в Виндовсе такого никогда не будет.

CC>А во всем остальном —


People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 06.04.07 18:27
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, c-smile, Вы писали:


CS>Поправка:


CS>Что дает применение:


CS>
CS>void foo( const boost::intrusive_ptr<T>& ptr ) 
CS>

CS>по сравнению с
CS>
CS>void foo( const T* ptr ) 
CS>


CS>Может я чего не понимаю но

CS>boost::intrusive_ptr<T> это средство memory management — т.е. при чем здесь параметры?

Во-первых, так просто зачатую делают, не задумываясь о том, что это под собой подразумевает
Действительно это обычно не надо

Во-вторых, я отталкивался от boost::shared_ptr, который надо передавать, что бы его потом можно было скопировать и сохранить на будущее (иногда это можно сделать имея указатель, но не всегда). Потом я заменил shared_ptr на intrusive_ptr, что бы сделать копирование полегче... в итоге пример получился не очень вразумительным т.к. действительно из голого указателя всегда можно восстановить intrusive_ptr.

Но в целом смысл был даже не в этом, смысл был в том, чтобы оценить разницу, когда у функции есть аргументы с нетривиальным деструктором и когда нет. Т.е. оценить, можно ли чего то добится, если некоторыми усилиями убрать из функции параметры с деструкторами.

Отсюда, в частности, следуют следующие выводы:
— объекты CString и подобные быстрее всё же передавать по сслыке (хоть они и используют COW), особенно если таким образом получится "разрузить" функцию от объектов с деструкторами. Т.к. исчезает установка/снятие фрейма исключений.
— код:
for (...) 
{
  f1();
}

void f1()
{
  std::string s;
  ...
}


можно попробовать переписать как-то так:

for (...) 
{
  std::string s;
  f1(s);
}

void f1(std::string& s)
{
  ...
}


таким образом тоже элиминируем установку/снятие фрейма исключений в f1().



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: 2 Andrew S: методика замера времени
От: remark Россия http://www.1024cores.net/
Дата: 06.04.07 18:47
Оценка:
Речь идёт о замере интервалов порядка десятков тактов.

Я предлагаю следующую методику:
Выполняем код много раз подряд.
Разы, в которые произошёл вызов планировщика, переключение контекста, страничное прерывание и т.д. отбрасываем, как выдающие заведомо оооочень большое неправильное время, никак не связанное с нашим измеряемым кодом.
Т.о. получаем "истинное" время выполнения целевого фрагмента кода.


Ты предлагаешь (поправь, где не прав):
Выполняем код много раз подряд.
Разы, в которые произошёл вызов планировщика, переключение контекста, страничное прерывание и т.д. учитываем.
Потом "размазываем" эти ооочень сильно большие времена, усредняя все значения.
Т.о. получаем "истинное" время выполнения целевого фрагмента кода.

Т.е. ты считаешь нормальным, если, например, при замере одного фрагмента кода переключения контекста произошли 1 раз, а во время замера второго фрагмента кода переключения контекста произошли 2 раза. Потом мы усредняем эти времена и сравниваем.

Т.е. ты считаешь нормальным, если произошёл вызов планировщика, потом одно переключение контекста, потом поработал другой поток, потом опять вызов планировщика, потом опять переключение контекста и потом продолжила работать наша функция. Это нормально, это время можно включить в замер функции в 20 тактов. А вот если ко всему этому прибавляется ещё и пенальти, вызванное переключением потока на другое ядро, то вот это ты считаешь не нормальным, и для борьбы с этим предлагаешь делать привязку потока к ядру.

Аналогичная ситуация с поднятием приоритета потока. Ты считаешь, что вызов планировщика совершенно нормально учитывать при замере куска кода.

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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 06.04.07 19:00
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Я конечно соглашусь, что по машинному коду можно сказать: "вот это написано на С++". Потому что RAII, ООП и т.п. дают отпечаток даже () на исходном коде (как правило машинный код в этом случае не лучший). Но нельзя сказать уверенно: "это написано на С". Может быть и на С++. Никто же не запретит писать на С++ (практически) как на С. Когда активно используют расширенные возмоности — это видно. Например, по лишнему коду можно отличить std::auto_ptr от голого указателя, автоматические вызовы *структоров в new и delete от "эмуляции" их на С. Хотя на С++ можно получить более компактный результат, поскольку проще оптимизировать на более высоком уровне. А вот лушчего машинного кода у С++ я не только никогда не видел, но даже не могу понять, как большая свобода компилятора этому может способствовать


В общем случае, если код делает одно и тоже, то и машинный код быдет таким же. Не виже никаких причин для обратного.

Вот набил такой пример:

__declspec(noinline) void auto_ptr()
{
    std::auto_ptr<int> i (new int(5));
}

__declspec(noinline) void by_hand()
{
    int* i = new int(5);
    delete i;
}

int main()
{
    auto_ptr();
    by_hand();
}


Ты не поверишь, но компилятор сделал следующее:


int main()
{
    auto_ptr();
0040109A  call        auto_ptr (401060h) 
    by_hand();
0040109F  call        auto_ptr (401060h) 
}
004010A4  xor         eax,eax 
004010A6  ret


Он даже не стал генерировать разных функций


Или вот ещё:


struct CPP
{
    int i;
    CPP()
    {
        __asm nop;
    }

    ~CPP()
    {
        __asm nop;
    }
};

struct C
{
    int i;

    void init()
    {
        __asm nop;
    }

    void deinit()
    {
        __asm nop;
    }
};

__declspec(noinline) void cpp()
{
    __asm nop;
    CPP cpp;
}

__declspec(noinline) void c()
{
    __asm nop;
    C c;
    c.init();
    c.deinit();
}

int main()
{
    cpp();
    c();
}



Машинный код:

__declspec(noinline) void cpp()
{
00401020  push        ecx  
00401021  nop              
00401022  lea         ecx,[esp] 
00401025  call        CPP::CPP (401000h) 
0040102A  lea         ecx,[esp] 
0040102D  add         esp,4 
00401030  jmp         CPP::~CPP (401010h) 



__declspec(noinline) void c()
{
00401040  push        ecx  
00401041  nop              
00401042  lea         ecx,[esp] 
00401045  call        init (401010h) 
0040104A  lea         ecx,[esp] 
0040104D  add         esp,4 
00401050  jmp         deinit (401010h)




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: 2 Andrew S: что мерить
От: remark Россия http://www.1024cores.net/
Дата: 06.04.07 19:22
Оценка:
Приведу твой ответ из ветки "Конструктив":

AS>Давай. Навскидку я вижу следующие паттерны:

AS>1. Чисто вычислительная функция — когда вызовов апи не производится вообще. Это может быть быть парсер текста, вычисление с использованием матриц и т.п. Желательно распределить их по степени сложности — глубины вызовов и количеству вызовов с проверками в одной функции.

согласен

AS>2. Обертки1. Когда ровно один слой и все сводится к вызову апи функции (или метода) и проверке возвращаемого значения\трансляции в исключение.


согласен — такой тест я делал

AS>3. Обертки1. Тоже ровно один слой, но в этом случае апи использует исключение (пример — MFC). Мы транслируем в свое исключение либо в код ошибки\возвращаемое значение.


в принципе не очень согласен но сделать можно, а потом пусть каждый сам решает насколько ему этот случай интересен

AS>4. Работа с файлами и анализ текста. Микс тест из 1, 2 и 3.


вот тут не очень понятно — ты что предлагаешь делать реальные вызовы ос?
я думаю, что это загубит весь тест, т.к. во-первых, время большое, а во-вторых, оно может сильно колебаться
а если не делать вызовов ос, то не понятно чем это отличается от (1)

AS>5. Смешанные вычисления — когда необходимо в процессе вычислений обращаться к апи. Сложность вычислений,процент обращений и характер распределения мест обработки по уровням можно регулировать (либо определить статистически общие варианты и использовать только их).


не понятно, чем отличается от (4)



что хотелось добавить — имхо тут надо делать всё-таки не очень нагруженные "мясом" тесты, что бы более "чисто" выделить вклад именно стратегий сообщения об ошибках. вызовы ос имхо накорню всё погубят. с вычислениями тоже надо быть осторожно — если тест получится memory bandwidth bound — то пиши пропало. т.е. имхо можно осторожно поделать какие-нибудь вычисления в регистрах, и повызывать заглушки ос. а в остальном оставить только "скелеты" от паттернов и при этом использовать невстраиваемые функции.


какие бы паттерны я добавил:
6. не понятно, почему обёртки в один слой. современные проекты насчитывают как минимум десяток слоёв (если считать в функциях), а то и больше. соответственно предлагаю мерить толстые обёртки. при этом варьировать толшину и ширину обёртки до "функций ос".

7. имхо обязательно надо мерить функции, использующие "ресурсы" — память/файлы/хендлы/соединения и т.д. в принципе это можно включить в предыдущий пункт, только варьировать ещё и кол-во ресурсов.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: 2 Andrew S: по поводу ebp
От: remark Россия http://www.1024cores.net/
Дата: 06.04.07 19:39
Оценка:
По поводу ebp я с одной стороны понял, а с другой не понял.

Понял, что при использовании исключений он может заниматься, и т.о. останется меньше регистров для вычислений.
Правда, имхо, такой эффект будет нетривиально отследить — надо сделать какой-то синтетический тест, которому требуется много регистров...


Не понял, когда и под что он занимается.
здесь
Автор: remark
Дата: 02.04.07
достаточно простенький пример и ebp _не_ занимается.
Почему и под что он будет заниматься в более сложных случаях?
Я бы понял, если бы наоборот — в простых он занимался, а в сложных освобождался каким-либо образом под другие нужны, а наоборот не понимаю...



Заодно по поводу thiscall. Для С случая нельзя использовать thiscall — его там нет. Поэтому всё же придётся мерить с cdecl.
Случай, когда в С++ используются возвращаемые значения, конечно, можно и надо мерить с thiscall.



По поводу сделать для случая С++ с возвращаемыми значениями вместо деструктора функцию deinit() — так не пойдёт. Даже если в С++ и используют функции типа init/create и т.д. вместо конструктора, то деструкторы используют даже самые вшивинькие библиотеки типа MFC/ACE. Поэтому я считаю, что случай с deinit() в С++ просто doesn't make any sense.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: 2 Andrew S: по поводу ebp
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.04.07 20:55
Оценка:
R>По поводу ebp я с одной стороны понял, а с другой не понял.

R>Понял, что при использовании исключений он может заниматься, и т.о. останется меньше регистров для вычислений.

R>Правда, имхо, такой эффект будет нетривиально отследить — надо сделать какой-то синтетический тест, которому требуется много регистров...

Эффект проявляется уже в простейших нагруженых функциях. Как пример — недавно делал блиттер. Так вот, этот несчастный один дополнительный регистр во внутреннем цикле давал +20% производительности. Ну мало регистров у х86, никуда от этого не уйти... Идиотизм, конечно, но тут все вопросы к Интел.

R>Не понял, когда и под что он занимается.

R>здесь
Автор: remark
Дата: 02.04.07
достаточно простенький пример и ebp _не_ занимается.

R>Почему и под что он будет заниматься в более сложных случаях?

Я привел код. Посмотри, там явно видно, под что.

R>Я бы понял, если бы наоборот — в простых он занимался, а в сложных освобождался каким-либо образом под другие нужны, а наоборот не понимаю...


Это как это наоборот? В простейших случаях компилятор может организовать вычисления стек-фрейма на esp, а в сложных ему это сделать не судьба — когда стек фрейм может раскручиваться как локальным исключением (фрейм, установленный в самой функции), так и во фрейм, установленный по вызову выше. В общем, ничего удивительного.

R>Заодно по поводу thiscall. Для С случая нельзя использовать thiscall — его там нет. Поэтому всё же придётся мерить с cdecl.


Случай "С" меня как то не очень интересует, откровенно говоря. Надо сравнивать сравнимое.

R>Случай, когда в С++ используются возвращаемые значения, конечно, можно и надо мерить с thiscall.


R>По поводу сделать для случая С++ с возвращаемыми значениями вместо деструктора функцию deinit() — так не пойдёт. Даже если в С++ и используют функции типа init/create и т.д. вместо конструктора, то деструкторы используют даже самые вшивинькие библиотеки типа MFC/ACE. Поэтому я считаю, что случай с deinit() в С++ просто doesn't make any sense.


Нет. Обычно init\destroy используют, когда имеются тривиальные конструкторы\деструкторы (которые инлайнятся), и тяжелые функции первичной\вторичной инициализации. Либо вообще не имеют конструкторов\деструкторов — получаются обычные POD. Поэтому именно то, что я приводил. А назвать MFC или ACE вшивенькой библиотекой — ну это да. Вообще, MFC как раз очень вполне завязана на исключения — посмотреть те же самые CFile.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[9]: [Investigation] оверхед std::auto_ptr
От: gear nuke  
Дата: 06.04.07 21:03
Оценка:
Здравствуйте, remark, Вы писали:

R>В общем случае, если код делает одно и тоже, то и машинный код быдет таким же. Не виже никаких причин для обратного.


auto_ptr делает несколько больше. Я же не писал "всегда отличается"

R>Ты не поверишь, но компилятор сделал следующее:


R>
R>int main()
R>{
R>    auto_ptr();
R>0040109A  call        auto_ptr (401060h) 
R>    by_hand();
R>0040109F  call        auto_ptr (401060h) 
R>}
R>004010A4  xor         eax,eax 
R>004010A6  ret

R>Он даже не стал генерировать разных функций

Поверю, у меня тела функций тоже получились идентичными, но в разных местах, поэтому хотелось бы узнать компилятор и ключи

Немного модернизировал пример, что бы было лучше видно лишнюю работу:

__declspec(noinline) void auto_ptr()
{
    std::auto_ptr<int> i /*(new int(5))*/;
}
>__declspec(noinline) void by_hand()
{
    int* i /*= new int(5)*/;
    //delete i;
}

int main()
{
    auto_ptr();
    by_hand();
}

MSVC 2005 + Dinkumware STL:
; Function compile flags: /Ogspy

?by_hand@@YAXXZ PROC                    ; by_hand
    ret 0
?by_hand@@YAXXZ ENDP                    ; by_hand

?auto_ptr@@YAXXZ PROC                   ; auto_ptr
    push    0
    call    ??3@YAXPAX@Z                ; operator delete
    pop ecx
    ret 0
?auto_ptr@@YAXXZ ENDP                   ; auto_ptr

_main   PROC
    call    ?auto_ptr@@YAXXZ            ; auto_ptr
    xor eax, eax
    ret 0
_main   ENDP

Конечно вырожденный случай, вот более жизненный:
__declspec(noinline) void auto_ptr()
{
    std::auto_ptr<int> i;
    int* i2 = new int(5);
    i.reset(i2);
}

__declspec(noinline) void by_hand()
{
    int* i;
    int* i2 = new int(5);
    i = i2;
    delete i;
}

int main()
{
    auto_ptr();
    by_hand();
}

MSVC 2005 + Dinkumware STL:
; Function compile flags: /Ogspy

?by_hand@@YAXXZ PROC                    ; by_hand
    push    4
    call    ??2@YAPAXI@Z                ; operator new
    test    eax, eax
    pop ecx
    je  SHORT $LN3@by_hand
    mov DWORD PTR [eax], 5
    jmp SHORT $LN4@by_hand
$LN3@by_hand:
    xor eax, eax
$LN4@by_hand:
    push    eax
    call    ??3@YAXPAX@Z                ; operator delete
    pop ecx
    ret 0
?by_hand@@YAXXZ ENDP                    ; by_hand

?auto_ptr@@YAXXZ PROC                   ; auto_ptr
    push    esi
    push    4
    call    ??2@YAPAXI@Z                ; operator new
    test    eax, eax
    pop ecx
    je  SHORT $LN3@auto_ptr
    mov DWORD PTR [eax], 5
    mov esi, eax
    jmp SHORT $LN4@auto_ptr
$LN3@auto_ptr:
    xor esi, esi
$LN4@auto_ptr:
    test    esi, esi
    je  SHORT $LN7@auto_ptr
    push    0
    call    ??3@YAXPAX@Z                ; operator delete
    pop ecx
$LN7@auto_ptr:
    push    esi
    call    ??3@YAXPAX@Z                ; operator delete
    pop ecx
    pop esi
    ret 0
?auto_ptr@@YAXXZ ENDP                   ; auto_ptr


В STLPort должны получиться похожие результаты.


Cитуацию (точнее, auto_ptr) можно немного исправить.

первый вариант:
; Function compile flags: /Ogspy
?auto_ptr@@YGXXZ PROC                  ; auto_ptr, COMDAT
    ret 0
?auto_ptr2@@YGXXZ ENDP                  ; auto_ptr

второй:
; Function compile flags: /Ogspy
;   COMDAT ?by_hand@@YGXXZ
_TEXT   SEGMENT
?by_hand@@YGXXZ PROC                    ; by_hand, COMDAT
; заинлайнен new:
    push    esi
    mov esi, 1280593503             ; 4c544e5fH
    push    esi
    push    4
    push    1
    call    DWORD PTR __imp__ExAllocatePoolWithTag@12
    test    eax, eax
    je  SHORT $LN3@by_hand
    mov DWORD PTR [eax], 5
    jmp SHORT $LN4@by_hand
$LN3@by_hand:
    xor eax, eax
$LN4@by_hand:
    test    eax, eax
    je  SHORT $LN12@by_hand
; заинлайнен delete
    push    esi
    push    eax
    call    DWORD PTR __imp__ExFreePoolWithTag@8
$LN12@by_hand:
    pop esi
    ret 0
?by_hand@@YGXXZ ENDP                    ; by_hand

?auto_ptr@@YGXXZ PROC                  ; auto_ptr, COMDAT
; заинлайнен new:
    push    esi
    mov esi, 1280593503             ; 4c544e5fH
    push    esi
    push    4
    push    1
    call    DWORD PTR __imp__ExAllocatePoolWithTag@12
    test    eax, eax
    je  SHORT $LN3@auto_ptr
    mov DWORD PTR [eax], 5
    jmp SHORT $LN23@auto_ptr
$LN3@auto_ptr:
    xor eax, eax
$LN23@auto_ptr:
    test    eax, eax
    je  SHORT $LN37@auto_ptr
; заинлайнен delete
    push    esi
    push    eax
    call    DWORD PTR __imp__ExFreePoolWithTag@8
$LN37@auto_ptr:
    pop esi
    ret 0
?auto_ptr@@YGXXZ ENDP                  ; auto_ptr

Текст примеров не изменён, исходный текст auto_ptr приведу следующим постом, этот и так уже большой

R>Или вот ещё:


[]

Аналогично — просто повезло Я о непонятной мне штуке с названием scalar deleting destructor
Автор: gear nuke
Дата: 17.11.05


People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: std::auto_ptr почти без оверхеда
От: gear nuke  
Дата: 06.04.07 21:09
Оценка:
template<class Y> struct auto_ptr_ref;

/// Class template auto_ptr [20.4.5 lib.auto.ptr]
template<class X>
class auto_ptr
{
  ///////////////////////////////////////////////////////////////////////////
  public:

    typedef X element_type;

    ///\name  construct/copy/destroy [20.4.5.1]

    explicit auto_ptr(X * p = 0)  throw() : ptr(p) {}

    auto_ptr(auto_ptr & a)        throw() : ptr(a.release()) {}

    template<class Y>
    auto_ptr(auto_ptr<Y> & a)     throw() : ptr(a.release()) {}

    __forceinline
    auto_ptr & operator=(auto_ptr & a) throw()
    {
      reset(a.release());
      return *this;
    }

    template<class Y>
    auto_ptr & operator=(auto_ptr<Y> & a) throw()
    {
      reset(a.release());
      return *this;
    }

    __forceinline
    ~auto_ptr() throw() { if ( get() ) delete get(); }

    ///\name  members [20.4.5.2]

    X & operator* ()  const throw() { return *get(); }
    X * operator->()  const throw() { return get(); }
    X * get()         const throw() { return ptr; }
    X * release()           throw() { X * tmp = get(); set(0); return tmp; }

    __forceinline
    void reset(X * p = 0)   throw()
    { 
      if ( get() && get() != p ) delete get();
      set(p);
    }

    ///\name  conversions [20.4.5.3]

    auto_ptr(auto_ptr_ref<X> r) throw() : ptr(r.ptr.release()) {}

    __forceinline
    auto_ptr & operator=(auto_ptr_ref<X> r) throw() { return *this = r.ptr; }

    template<class Y>
    operator auto_ptr_ref<Y>()  throw() { return auto_ptr_ref<Y>(*this); }

    template<class Y>
    operator auto_ptr<Y>()      throw() { return auto_ptr<Y>(release()); }

    ///@}

  ///////////////////////////////////////////////////////////////////////////
  private:
  
    X * ptr;
    void set(X * p) { ptr = p; }
};

template<class Y>
struct auto_ptr_ref
{
    auto_ptr_ref(auto_ptr<Y> & a) throw() : ptr(a) {}
    auto_ptr<Y> & ptr;
  private:
    auto_ptr_ref<Y> & operator=(const auto_ptr_ref<Y> &);
};
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: 2 Andrew S: методика замера времени
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.04.07 21:27
Оценка: -1
R>Речь идёт о замере интервалов порядка десятков тактов.

Десятков???? Десятков тысяч. Или ты про разницу?

R>Я предлагаю следующую методику:

R>Выполняем код много раз подряд.
R>Разы, в которые произошёл вызов планировщика, переключение контекста, страничное прерывание и т.д. отбрасываем, как выдающие заведомо оооочень большое неправильное время, никак не связанное с нашим измеряемым кодом.
R>Т.о. получаем "истинное" время выполнения целевого фрагмента кода.

Планировщик вызывается раз в ~15мс. Ты действительно думаешь, что он не влияет на результаты замеров? Еще раз — чтобы снизить влияние планировщика, надо поднять приоритеты и увеличить время замеров до нескольких (десятков) минут.

R>Ты предлагаешь (поправь, где не прав):

R>Выполняем код много раз подряд.

Много _тысяч_ раз подряд.

R>Разы, в которые произошёл вызов планировщика, переключение контекста, страничное прерывание и т.д. учитываем.


Мы их в любом случае учитываем. Ты в мультизадачной ОС. Прервать выполнение кода может не только планировщик — еще есть аппаратные прерывания, DMA, и многие другие вещи, неявно влияющие на производительность памяти, процессора и т.п.

R>Потом "размазываем" эти ооочень сильно большие времена, усредняя все значения.


Нет. Времена будут примерно одинаковые. Почитай статью по ссылке, там пояснено, как что и почему. Я уже устал говорить, что время выполнения в современных программно-аппаратных системах зависит не только от программной, но и той аппаратной части (юнита), на котором исполняется код. А с учетом всяких "прикольных" чипсетов типа KT133 с его закидонами с шиной — так и вообще от фазы луны. Поэтому надо использовать длительные измерения, а влияние перепланировки уменьшать путем повышения приоритета. Право — это же азы.

R>Т.о. получаем "истинное" время выполнения целевого фрагмента кода.


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

R>Т.е. ты считаешь нормальным, если, например, при замере одного фрагмента кода переключения контекста произошли 1 раз, а во время замера второго фрагмента кода переключения контекста произошли 2 раза. Потом мы усредняем эти времена и сравниваем.


Нет. Я считаю нормальным, когда за время замера переключение контекста произошло 100000 или 100010 раз.

R>Т.е. ты считаешь нормальным, если произошёл вызов планировщика, потом одно переключение контекста, потом поработал другой поток, потом опять вызов планировщика, потом опять переключение контекста и потом продолжила работать наша функция. Это нормально, это время можно включить в замер функции в 20 тактов. А вот если ко всему этому прибавляется ещё и пенальти, вызванное переключением потока на другое ядро, то вот это ты считаешь не нормальным, и для борьбы с этим предлагаешь делать привязку потока к ядру.


Ты все в кашу мешаешь... Даже не буду комментировать, но право, рекомендую разобраться, что к чему и зачем. К одному ядру я рекомендую привязывать по совершенно другим причинам. И я о них уже говорил.
Ты, например, даже не учитываешь, что RDTSC замеряет совсем не время выполнения кода, а совершенно другое — пропускную способность декодера команд. Поэтому все твои измерения с точностью до 20 команд — пшик. Конвейер у того же П4 — 18-20 стадий, что ты меряешь? Почитай статью — там хороший пример. ПОэтому надо мерить не 20 тактов, а 200000 тактов. Тогда точность измерения будет приемлемой (инструмент измерений не будет влиять на измеряемый объект). Между вызовами точек отсчета должны проходить десятки, а лучше сотни тысяч команд.

R>Аналогичная ситуация с поднятием приоритета потока. Ты считаешь, что вызов планировщика совершенно нормально учитывать при замере куска кода.


Без этого — никак. Хочешь отключить планировщик? Работай в DOS

R>Ну уж извините, с таким подходом я в корне не согласен. Хоть убейте.


Ну, можно не соглашаться с теорией относительности, или с тем, что в одном рубле 100 копеек. Но от этого она (ТО) не станет более верной или не верной, а рубль не полегчает и тяжелее тоже не станет. Есть испытанные методики измерения времени выполнения кода. Про них тебе уже говорили несколько разных людей, не только я.
Все, эта тема для меня закрыта — нового я тебе ничего не скажу, ты мне — тоже . Право, ходим по кругу — я не вижу смысла продолжать.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: [Investigation] Exceptions vs. Return Values
От: Константин Россия  
Дата: 31.01.08 10:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>То, что исключения позволяют сократить один if при вызове функции, по-моему, с лихвой компенсируется тем, что исключения вынуждают пользоваться обертками в виде умных указателей.


"Вы поставили знак минус вместо знака плюс"


Выделенное нужно заменить на и бесплатно получаем

Уже ради этих обеих вещей стоит использовать исключения
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.