Об оптимизации
От: Mamut Швеция http://dmitriid.com
Дата: 26.06.08 10:26
Оценка:
Помню, что эта тема не раз обсуждалась, но что-то сейчас я найти ее не могу.

Часто говорится о том, что JIT'у доступны оптимизации, которые C++ — компилятору и не снились

Можно поинтересоваться — какие
... << RSDN@Home 1.2.0 alpha 4 rev. 1091>>


dmitriid.comGitHubLinkedIn
Re: Об оптимизации
От: pgregory Россия  
Дата: 26.06.08 10:32
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Помню, что эта тема не раз обсуждалась, но что-то сейчас я найти ее не могу.


M>Часто говорится о том, что JIT'у доступны оптимизации, которые C++ — компилятору и не снились


M>Можно поинтересоваться — какие :)


Выкидывание динамически мертвого кода, например
--
In code we trust.
Re[2]: Об оптимизации
От: chukichuki  
Дата: 26.06.08 10:58
Оценка:
Здравствуйте, pgregory, Вы писали:

P>Выкидывание динамически мертвого кода, например


эээ ... например ? Насколько представляю себе процедуру JIT тот же компилятор, только срабатывает он не в момент сборки программы, а непосредственно перед ее запуском. Или он в процессе работы программы анализирует как она выполняется и еще что-то там компилирует дополнительно ?
Re: Об оптимизации
От: Klapaucius  
Дата: 26.06.08 11:05
Оценка: 26 (1) +1
Здравствуйте, Mamut, Вы писали:

M>Помню, что эта тема не раз обсуждалась, но что-то сейчас я найти ее не могу.


M>Часто говорится о том, что JIT'у доступны оптимизации, которые C++ — компилятору и не снились


M>Можно поинтересоваться — какие


Инлайнинг
Автор: Klapaucius
Дата: 13.06.07
виртуального вызова из другой библиотеки
Автор: Klapaucius
Дата: 15.06.07
, например.
... << RSDN@Home 1.2.0 alpha 4 rev. 1090>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re: Об оптимизации
От: chukichuki  
Дата: 26.06.08 11:17
Оценка: 26 (1)
Здравствуйте, Mamut, Вы писали:

M>Можно поинтересоваться — какие


Поверхностный гуглинг дал следующий результат

http://vladweb.narod.ru/help/csharp/csharp_req.htm

Оптимизации, присущие только JIT

Поскольку JIT активизируется во время выполнения, он использует большое количество информации, которую не может использовать компилятор. Это позволяет осуществлять некоторые оптимизации, которые доступны только во время выполнения:

* Процессор-специфические оптимизации — Во время выполнения JIT знает о том, может ли он использовать инструкции SSE или 3DNow. Ваш выполняемый файл будет скомпилирован специально для P4, Athlon или любого другого семейства процессоров. Будучи однажды созданным, тот же код будет совершенствоваться вместе с JIT и машиной пользователя.
* Удаление уровней преобразования логических адресов в физические, т.к. расположение функции и объекта доступны во время выполнения.
* JIT может осуществлять оптимизации через сборки, обеспечивая множество преимуществ, получаемых вами при компилировании программы со статическими библиотеками, но сохраняя гибкость и небольшие последствия использования динамических библиотек.
* Активные inline функции, вызываются чаще, т.к. во время выполнения учитывается управляющая логика. Оптимизации могут обеспечить существенное повышение скорости, и остается еще большое поле для улучшений в следующих версиях.

1 понятно.
2 вообще не понял, это как на пальцах.
3 тоже
4 понятно. Более того, чисто теоретически фичу анализа статистики выполнения кода можно использовать не только для того чтобы функции инлайнить. Есть неоднозначные оптимизации. Их целесообразность можно определить только зная как будет выполняться программа, что в компайл-тайме не всегда можно сделать. Статистика выполнения здесь на руку. Другое дело, что на сбор подробной статистики может уходить много процессорного времени и памяти ...
Re[3]: Об оптимизации
От: pgregory Россия  
Дата: 26.06.08 11:17
Оценка:
Здравствуйте, chukichuki, Вы писали:

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


P>>Выкидывание динамически мертвого кода, например


C>эээ ... например ? Насколько представляю себе процедуру JIT тот же компилятор, только срабатывает он не в момент сборки программы, а непосредственно перед ее запуском. Или он в процессе работы программы анализирует как она выполняется и еще что-то там компилирует дополнительно ?


http://en.wikipedia.org/wiki/Just-in-time_compilation

Конечно! В этом все и дело.
Вот очень интересный реальный пример: http://lists.cs.uiuc.edu/pipermail/llvmdev/2006-August/006492.html
--
In code we trust.
Re[2]: Об оптимизации
От: Erop Россия  
Дата: 26.06.08 11:22
Оценка: +1
Здравствуйте, pgregory, Вы писали:

P>Выкидывание динамически мертвого кода, например

Это ты о неиспользуемых функциях типа? Ну дык мапирование exe'шников на память справляется с этим не хуже
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Об оптимизации
От: pgregory Россия  
Дата: 26.06.08 11:26
Оценка:
Здравствуйте, Erop, Вы писали:

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


P>>Выкидывание динамически мертвого кода, например

E>Это ты о неиспользуемых функциях типа? Ну дык мапирование exe'шников на память справляется с этим не хуже :shuffle:

Нет, я, например, о функции, содержащей кучу if-ов, которые меняются крайне редко.
Она из кошмара для бранч-предиктора превращается в конфетку.

Пример я уже приводил: http://lists.cs.uiuc.edu/pipermail/llvmdev/2006-August/006492.html
--
In code we trust.
Re[3]: Об оптимизации
От: fmiracle  
Дата: 26.06.08 11:45
Оценка:
Здравствуйте, chukichuki, Вы писали:

P>>Выкидывание динамически мертвого кода, например


C>эээ ... например ? Насколько представляю себе процедуру JIT тот же компилятор, только срабатывает он не в момент сборки программы, а непосредственно перед ее запуском. Или он в процессе работы программы анализирует как она выполняется и еще что-то там компилирует дополнительно ?


Даже текущий компилятор .NET компилирует не всю программу перед запуском, а по мере необходимости функций.

Соответственно возможен такой пример:

class Helper
{
  static readonly bool _debugMode = GetDebugModeFromAppConfig();

  public DoAction()
  {
    if( _debugMode )   //код в этом ифе вообще не будет скомпилирован если в конфигурационном файле(!) отключен дебаг-режим.
    {
       //do something
    }
  }
}


Жавовский HotSpot, насколько я помню, накапливает статистику работы и перекомплирует функции в соответствии с ними.
Re[2]: Об оптимизации
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.06.08 12:07
Оценка: 13 (1)
Здравствуйте, chukichuki, Вы писали:
C>Поскольку JIT активизируется во время выполнения, он использует большое количество информации, которую не может использовать компилятор. Это позволяет осуществлять некоторые оптимизации, которые доступны только во время выполнения:

C> * Процессор-специфические оптимизации — Во время выполнения JIT знает о том, может ли он использовать инструкции SSE или 3DNow. Ваш выполняемый файл будет скомпилирован специально для P4, Athlon или любого другого семейства процессоров. Будучи однажды созданным, тот же код будет совершенствоваться вместе с JIT и машиной пользователя.

C> * Удаление уровней преобразования логических адресов в физические, т.к. расположение функции и объекта доступны во время выполнения.
C> * JIT может осуществлять оптимизации через сборки, обеспечивая множество преимуществ, получаемых вами при компилировании программы со статическими библиотеками, но сохраняя гибкость и небольшие последствия использования динамических библиотек.
C> * Активные inline функции, вызываются чаще, т.к. во время выполнения учитывается управляющая логика. Оптимизации могут обеспечить существенное повышение скорости, и остается еще большое поле для улучшений в следующих версиях.

C>1 понятно.

C>2 вообще не понял, это как на пальцах.
Ты себе представляешь, как работает статический импорт из DLL? Какие именно ассемблерные инструкции выполняются?
C>3 тоже
Это почти что то же самое, что и 2.
C>4 понятно. Более того, чисто теоретически фичу анализа статистики выполнения кода можно использовать не только для того чтобы функции инлайнить.
Это чистая практика.
C> Есть неоднозначные оптимизации.
Их принято называть "спекулятивными".
C>Их целесообразность можно определить только зная как будет выполняться программа, что в компайл-тайме не всегда можно сделать. Статистика выполнения здесь на руку. Другое дело, что на сбор подробной статистики может уходить много процессорного времени и памяти ...
Не так уж много. Есть два подхода: Profile-Guided Optimization и HotSpotting.
В первом программа сначала собирается без оптимизаций и гоняется под профайлером на тестовой нагрузке. Затем компилятору скармливается опять исходник, но на этот раз вместе с профилем программы. В итоге имеем высокооптимальную программу без затрат времени на оптимизацию в рантайме.
Во втором случае статистика выполнения собирается в рантайме — это не очень дорого; в простом случае достаточно раз в некоторое время засекать значение регистра EIP, чтобы понять, где программа проводит больше всего времени. Ну и накопленная статистика потребляется джит-компилятором для улучшения кода. Дополнительные затраты на оптимизацию окупаются в том случае, если нагрузка на систему трудно предсказуема на этапе разработки.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Об оптимизации
От: chukichuki  
Дата: 26.06.08 12:45
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Не так уж много. Есть два подхода: Profile-Guided Optimization и HotSpotting.

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

Чисто теоретически на это способны и обычные компиляторы в связке с профилировщиком. JIT для этого не нужен.

S>Во втором случае статистика выполнения собирается в рантайме — это не очень дорого; в простом случае достаточно раз в некоторое время засекать значение регистра EIP, чтобы понять, где программа проводит больше всего времени. Ну и накопленная статистика потребляется джит-компилятором для улучшения кода. Дополнительные затраты на оптимизацию окупаются в том случае, если нагрузка на систему трудно предсказуема на этапе разработки.


Следить за EIP самый простой случай, который много информации не даст. Максимум по таким данным функцию какую-нибудь заинлайнить можно или особо прожерливый цикл развернуть. Правильно выстроить условия if-ов (выше кто-то приводил пример) чтобы блок предсказания переходов процессора с ума не сходил уже наверное не получится.
Re[4]: Об оптимизации
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.06.08 02:23
Оценка:
Здравствуйте, chukichuki, Вы писали:

C>Чисто теоретически на это способны и обычные компиляторы в связке с профилировщиком.

Уже и чисто практически. MS VS поддерживает PGO начиная с 2005.
C> JIT для этого не нужен.
Совершенно верно. Этот подход работает для любых языков, в том числе и со статической компиляцией.

S>>Во втором случае статистика выполнения собирается в рантайме — это не очень дорого; в простом случае достаточно раз в некоторое время засекать значение регистра EIP, чтобы понять, где программа проводит больше всего времени. Ну и накопленная статистика потребляется джит-компилятором для улучшения кода. Дополнительные затраты на оптимизацию окупаются в том случае, если нагрузка на систему трудно предсказуема на этапе разработки.


C>Следить за EIP самый простой случай, который много информации не даст.

Ты не поверишь: основые улучшения достигаются самыми простыми методами
C>Максимум по таким данным функцию какую-нибудь заинлайнить можно или особо прожерливый цикл развернуть.
C>Правильно выстроить условия if-ов (выше кто-то приводил пример) чтобы блок предсказания переходов процессора с ума не сходил уже наверное не получится.
Конечно же получится. Если мы видим, что EIP проводит больше времени в одной ветке if, чем в другой, то информации уже достаточно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Об оптимизации
От: chukichuki  
Дата: 27.06.08 06:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Следить за EIP самый простой случай, который много информации не даст.

S>Ты не поверишь: основые улучшения достигаются самыми простыми методами
C>>Максимум по таким данным функцию какую-нибудь заинлайнить можно или особо прожерливый цикл развернуть.
C>>Правильно выстроить условия if-ов (выше кто-то приводил пример) чтобы блок предсказания переходов процессора с ума не сходил уже наверное не получится.
S>Конечно же получится. Если мы видим, что EIP проводит больше времени в одной ветке if, чем в другой, то информации уже достаточно.


Во-первых просто по EIP-у достоверная информация получается только в ряде совсем уж примитивных случаев. Например, случай по сложнее. Пусть имеется

if (cond) {
  DoSomething1();
} else {
  DoSomething2();
}


Анализ EIP-а показыват что больше всего времени программа проводит в DoSomething1(). Какие можно сделать выводы относительно частот срабатываний разных веток if-а? Только по значению EIP-а почти никаких. Во первых неплохо бы удостовериться что DoSomething1() был вызван именно из приведенного выше фрагмента, а не из какого-нибудь другой части программы. Значит надо просмотреть стек вызовов. Во вторых неплохо бы удостоверится что DoSomething1() вызывается многократно. Только в этом случае имеет смысл оптимизировать условие if-а. Т.е. надо хранить статистику по вызовам функций. Причем, не просто статистику по вызовам, а по вызовам функций именно из определенного места программы. Ведь DoSomething1() может вызываться еще в куче разных мест. И только в том случае если DoSomething1() в этой ветке вызывается гораздо больше раз чем DoSomething2() в противоположной ветке надо что-то оптимизировать. Можно сделать проще и универсальнее — достаточно считать количество срабатываний отдельных веток if-а. Ну т.е. на каждую ветку каждого условного оператора завести отдельную ячейку памяти, которая бы считала какая ветка выполняется чаще.
Re[6]: Об оптимизации
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.06.08 07:18
Оценка: 4 (1)
Здравствуйте, chukichuki, Вы писали:
C>Можно сделать проще и универсальнее — достаточно считать количество срабатываний отдельных веток if-а. Ну т.е. на каждую ветку каждого условного оператора завести отдельную ячейку памяти, которая бы считала какая ветка выполняется чаще.
Правильно. См. http://wikis.sun.com/display/HotSpotInternals/PerformanceTechniques, раздел Profiling.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Об оптимизации
От: Pavel Dvorkin Россия  
Дата: 01.07.08 06:33
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Можно поинтересоваться — какие


Если очень коротко, то

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

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

Но JIT надо работать быстро, иначе программа будет работать медленно. Быстро — это значит, что если обычный компилятор и JIT написаны одинаково качественно, то качество оптимизации JIT будет хуже, чудес не бывает. У обычного компилятора на оптимизацию времени сколько угодно, и если он большой проект будет час компилировать, то это не так уж важно.
With best regards
Pavel Dvorkin
Re[2]: Об оптимизации
От: minorlogic Украина  
Дата: 01.07.08 07:05
Оценка:
PD>Но JIT надо работать быстро, иначе программа будет работать медленно. Быстро — это значит, что если обычный компилятор и JIT написаны одинаково качественно, то качество оптимизации JIT будет хуже, чудес не бывает. У обычного компилятора на оптимизацию времени сколько угодно, и если он большой проект будет час компилировать, то это не так уж важно.

Можно не согласиться. Дело в том что JIT может оптимизировать только горячие участки и относительно статической компиляции уделять им больше времени.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Об оптимизации
От: Pavel Dvorkin Россия  
Дата: 01.07.08 07:21
Оценка:
Здравствуйте, minorlogic, Вы писали:

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


И все же не час.
With best regards
Pavel Dvorkin
Re[2]: Об оптимизации
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.07.08 08:21
Оценка: -1
Здравствуйте, Pavel Dvorkin, Вы писали:

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

Неверно. JIT компилирует не высокоуровневый код, а IL. JIT компилирует не всю программу, а по частям. Поэтому вполне возможно что JIT будет лучше оптимизировать код, чем обычный компилятор за приемлмое время. А учитывая что JIT компилирует один раз, то даже разница на порядок во времени работы JITа будет незначительной.
Re[4]: Об оптимизации
От: fmiracle  
Дата: 01.07.08 10:44
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PD>И все же не час.


час-то на все, а тут только несколько реально критичных методов, которые надо перекомпилировать.
Re[3]: Об оптимизации
От: Pavel Dvorkin Россия  
Дата: 01.07.08 10:48
Оценка: -4
Здравствуйте, gandjustas, Вы писали:

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


Ну здесь мы бумерангом ту же ситуацию обратно получаем. JIT — да, но при компиляции с исходного кода компилятор с C#, к примеру, не знает, на какую обстановку это ориентировано. И не знает хуже, чем обычный компилятор. Тот, к примеру, может учесть специфику x86-x64 со всеми конвейерами и микрооперациями (как Intel C++) или Intel-AMD (последнее маловероятно, конечно, но мы же о принципах говорим), а компилятор C#, если явно не указана платформа, вынужден делать в расчете на произвольную платформу. А оптимизацию ИМХО все же лучше делать с исходного языка, а не с псевдоассемблера (IL) — информации для принятия решений больше.
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.