Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.218.38.125] |
|
Страницы: (77) « Первая ... 6 7 [8] 9 10 ... 76 77 ( Перейти к последнему сообщению ) |
Сообщ.
#106
,
|
|
|
Славян и другие
Не вижу смысла пользоваться такими заумными конструкциями. Если ты знаешь, что там ноль, то так и пиши =0, нечего компилятору голову морочить, и тем кто потом программу читать будет (в основном им). |
Сообщ.
#107
,
|
|
|
Славян
Цитата Славян @ Вот когда ты будешь обладать не меньшим количеством информации, чем оптимизатор, тогда ты сможешь считать, что усиливаешь его. Заметь, он обладает куда бОльшей информацией о сгенерированном коде, чем ты, рассматривая ассеблерный листинг вблизи места предполагаемого вмешательства. А пока ты не доказал, хотя бы себе, что: считай, что ты оптимизатору будешь только мешать, ибо он тебя послушается даже в ущерб своей задаче. Даже выиграв локально тут, в целом можешь проиграть крупнее где-нибудь там, и не заметить этого. 2.Это не оптимизатор считает что-то нужным, а люди думают, сколько они сил готовы потратить, чтобы усилить оптимизатор. И часто махают рукой. |
Сообщ.
#108
,
|
|
|
Qraizer, все это замечательно. Только здесь же в холиварах ассемблерщики показывают, что оптимизатор (практически во всех перечисленных тобою пунктах) сливает проф. ассемблерщику. Т. е. я хочу сказать, что какие-то оптимизаторы, может быть, и умеют оптимизировать так, как ты описал, но таких - единицы. И те же компиляторы от Intel и Microsoft такими свойствами не обладают. Если считаешь иначе, прошу вот в эту: http://forum.sources.ru/index.php?showtopic=209970 тему.
|
Сообщ.
#109
,
|
|
|
Чесговоря, не нашёл я в этом топике того, что ты мне хотел показать. Читал не весь - большой уж больно - так что ткни меня носом конкретнее, плз. Либо я не понял, чтО ты хотел мне показать. Я подумал что "ассемблерные профессионалы, затыкающие оптимизаторы без особых усилий - это не редкость". Так что проясни, если не трудно.
Далее. Оптимизаторы, которые я имел в виду, отнюдь не редкость. Только надо предоставить им достаточно информации для работы. Например, размеры строк кеша зависят от процессора, поэтому пока не укажешь оптимизатору каким-нибудь ключиком /G7 /QxP, на чём будет исполняться программа, максимум отдачи не получишь. Согласен, что несерьёзно настолько конкретизировать исполнительную платформу, но во-первых, ручной ассемблерный код тоже подвержен влиянию этой проблемы, во-вторых, есть ещё, к примеру, /QaxW, в-третьих, и вручную тоже можно разделить код под разные процессоры путём __declspec(cpu_specific) и __declspec(cpu_dispatch) и даже не использовать при этом ассемблер. Что касается потери оптимизации в общем при некотором выигрывании в частном, то /Qip сможет помочь, причём даже есть ассемблер, тут я слегка сутрировал, признаю. А для экстремалов есть /Qipo, только при его применении в зависимости от размера проекта в ожидании окончания его компиляции можно зачаржить часы в недельном отчёте от "отправился на обед" до "уехал на пикник". Для эстетов имеется /Qprof_gen и /Qprof_use, заодно и целевой модуль может получиться меньше в разы. Ну и наконец, всё это фуфло по сравнению с jit-time компиляцией. Правда, это уже не для плюсов. По крайней мере, пока. Недаром байт-кодинг в последнее время получает всё большее расспространение, ИМХО дойдёт и до плюсов. Зато решает проблемы с зависимостью от исполнительной платформы. Только, боюсь, здесь уже ассемблер будет просто в оффсайте. А если попытаться его заменить каким-нибудь специальным байт-кодным ассемблером, то это опять-таки внесёт уровень трансляции, который ассемблерные вставки призваны вроде как наоборот - убирать. P.S. Примеры управления оптимизацией взяты от Intel Compiler. Несколько слов в защиту обоих точек зрения: генерим ассемблерный вывод и внимательно рассматриваем комменты Intel Compilr-а, которыми он подробненько расписал, что по его мнению будет происходить при исполнении кода - всякие там штрафы от простоев, вероятности предсказаний переходов, распределение данных по строкам кеша и вероятности промахов, итп, и только после этого приступаем к попыткам помочь ему в каких-нибудь конкретных местах. Это я ещё смогу понять. В заключение. Я не отрицал возможности переплюнуть оптимизатор, так и сказал: "...пока ты не доказал, хотя бы себе,...". Если удалось доказать - то флаг в руки. Но лично мне это неинтересно. Каждый получает удовольствие от разных аспектов творческой составляющей нашей профессии. И я уже давно бросил соревноваться с компилятором в такой рутинной (для меня) области как бак-энд оптимизэйшн. Когда понадобилось написать _ecvtl() и _fcvtl для нативного x86-го long double, которые как известно MSVC для Win32 не поддерживает, тогда я этим занялся. Писал на асме и оптимизировал под P6. И - не буду скромничать - переплюнул их собственный _ecvt в три раза в производительности, а аналогичную C-реализацию компилятор соптимизировал хуже на 15%. И только добавив /arch:SSE2, я смог добиться от компилятора большей эффективности, что всё равно было неприемлимо, ибо функция как бы библиотечная. Потратил на это около двух дней - примерно впополаме на создание/отладку и оптимизацию/отладку. Теперь могу гордиться, мол, моя функция экономит вам столько-то там миллисекунд на выводе каждого long double. Вот пишу сейчас и думаю, нафиг я на это потратил столько времени? Разве что здесь похвастаться, а так практического эффекта никто не заметил и никогда не заметит. Да и было это один-единственный раз за последние лет восемь. В общем, мне это неинтересно, я лучше найду более другие причины потратить своё рабочее время. С пользой в сторону переносимости, гибкости, масштабируемости и надёжности. Если у кого другое ИМХО, да пожалуйста. Только для предотвращения воизбежания пусть почитает обо всём этом тут, ну а там пусть делает свои выводы и поступает сообразно им. Да и не всем "двигать мировую экономику и внедрять демократию", кому-то надо "...быть спортсменом или клоуном, чтоб политики и демократы могли иногда отдохнуть от подгаживания своим коллегам и расслабиться под зрелище смачной драки футбольных фанатов или там резню гладиаторов..." © Гай Юлий Орловский. |
Сообщ.
#110
,
|
|
|
Блин, как всё сложно. Просто, поверите ли нет, ну дураку понятно, что код вида :
mov edi, edi push ebp mov ebp, esp mov eax, [eax+$xxyyzzww] pop ebp ret // вроде User32.dll или вида fld1 fstp dword ptr [EBP+$xx] fldz fstp dw [EBP+$yy] fldz fstp dw [EBP+$zz] fldz fstp dw [EBP+$ww] fld1 fstp dword ptr [EBP+$hh] ... // glu32.dll не является оптимальным ну никак. И всякие оптимизации, приводящие к коду типа 1-примера( когда нефиг напрягаться компилятору за стэк), очевидно глупее моих : mov eax, [eax+$...] ret Мне не нужно изучать кэши и промахи в него, ибо я суть оптимизатора вижу. И уж поверьте хоть и смотрю 'листинг вблизи места', вижу больше, чем он. Ну на кой ляд делать код fld ... fld ... fxch ST(1), ST(0) ... И таких примеров у меня уже 76 категорий накопилось. Собираю, знаете ли ;-) Баг ниже вообще заполонил Microsoft'овские dll-ки. [BUG70] 648B05xxyy0000 mov EAX, FS:[$0000yyxx] :или 64A1xxyy0000 : mov EAX, FS:[$0000yyxx] : можно сэкономить на нулях! (используя префикс : смены способа адресации) так : 6764A1xxyy : mov EAX, FS:[$yyxx] : выигрыш = 2 байта(в 1 случае), или 1 байт (во втором)! : истинность = 100% (вроде бы) : идея баг'а из WinXP sp2 : user32.dll |
Сообщ.
#111
,
|
|
|
Мда, маловаты у тебя фрагменты, как-то ты черезчур буквальНо поспринял слово "вблизи". Так что на безгрешность не претендую, однако...
С первым примером для меня всё ясно. Первая инструкция - это двухбайтный ноп. Для чего он там - это вопрос уже не ко мне. Даже после самых дерьмовых оптимизаторов просто так нопы никогда не остаются, т.е. к оптимизации он не имеет прямого отношения. Игра со стековым фреймом - так без него плохо живётся всяким там отладчикам, профайлерам, кодековерам итп. А экспортируемые функции без стекового фрейма - это вообще нонсенс. Менеждер виртуальной памяти может это не одобрить по полной программе. Вообще же, ставишь галку компилеру, и он напрочь забывает о фреймах. И наоборот: не поставил галку - компилятор обязан создавать фреймы. Что, скажешь ни разу этой галкой не пользовался? Что-то я не пойму твоего недовольства этим фрагментом. Второй фрагмент вполне оптимален. Наверняка компилятору было сказано ключиком, чтобы он использовал строгое соответствие стандарту IEEE при работе с вещественной арифметикой. Вот он и не стал заменять FPU операции на CPUшные. А дальше я бы лучше уточнил, для какого процессора это оптимизация. Я вижу множество только-записей на шину, разделёнными паузами для предотвращения простоя блока предвыборки, который имеет меньший приоритет при конкуренции за грант шины по сравнению с записью данных. Паузы маленькие, всего в две микроинструкции + имеем простаивающий третий декодер, который компилятору просто нечем загрузить (впрочем, для P5 - этот код оптимизарован почти абсолютно), но если вдруг что, то одна из них даст возможность простаивающему блоку предвыборки успеть озадачить кеш, и в случае промаха теперь уже записи будут откладываться в буфере в ожидании гранта на шину. Вносимые fldz и fld1 паузы сами по себе не вредят производительности, т.к. эти команды на самом деле просто возвращают некое значение, которое тут же отправляется в память, т.е. в блоке неупорядоченного исполнения все они в совокупности не будут порождать никаких штрафов из-за зависимости по ST(0). Точнее, это всё-таки может случиться, но зависеть будет не от этого кода, а от окружающего контекста. Третий фрагмент - это вообще классика, начиная с P5. То, что тебе показалось глупостью, на самом деле позволяет выполняться последней загрузке параллельно со следующей после FXCH FPU-операцией, т.к. FXCH - это чуть ли не единственная инструкция, которая парабельна почти всем остальным FPU инструкциям (исключая трансцендентные, кажется). Выполняя её одновременно с предыдущей, мы ничего не теряем в тактах, зато "переименовываем" ST(0) в (в данном случае) ST(1), и следовательно какая-нибудь следующая FADD ST(0), ... будет работать параллельно с загрузкой в ST(1). Для P6 это имеет более слабый эффект, особенно на нативном для x86 long double, но всё-таки имеет. Четвёртый пример ты бы постеснялся приводить, если бы е лез в бутылку, а внимательнее внимал. Этот "баг" самое что ни на есть распространённое средство выравнивать длины инструкций под наиболее оптимальные. Так же как с нопами - иногда выгоднее использовать покороче, иногда - подлиннее. А вот твоя "оптимизация" предлагает поставить два префикса подряд, причём один из них AS. Ну-ну. Я думаю, не имеет смысла рассматривать все 76 категорий. Это число как-то подозрительно напоминает длину моего конспекта по оптимизации i486-P7, там было что-то около 70 пунктов. Да и archimed7592 прав - ты спросил, я ответил, а дальше давай куда-нибудь от этого топика, если будет желание. Только до окончания праздников, боюсь, у меня будут сложности с on-line-ом. И кстати, archimed7592 напомнил, инициализация присваиванием и твоя логической операцией нагружают разные исполнительные блоки процессора. Именно поэтому иногда оптимизаторы используют твою идею, иногда нет. Нагружает так, чтобы получилось поравномернее, а если в данном кокретном случае пофигу, то просто юзают "прямой" способ. |
Сообщ.
#112
,
|
|
|
Вы когда спорите со Славяном, держите в уме вот это: Определить бинарный файл (сообщение #1816742) и вот это: Определить бинарный файл (сообщение #1817916)
|
Сообщ.
#113
,
|
|
|
Я только начинаю учить шаблоны поэтому мне не очень понятно тут все В первом сообщении думал -
Цитата что текущий стандарт, для заданного выражения E(a1,a2,...,aN), которое зависит от параметров a1,a2,...,aN, не позволяет написать такую ф-цию(или функтор), которая будет эквивалентна этому выражению. Думаю как это так? Ну например a1+a2+a3. Почему нельзя сделать функцию с параметрами a1,a2,a3, в которой будет строчка return a1+a2+a3? Потом идет первый пример - где "Всё бы хорошо, но нельзя сделать вызов f(1, 2, 3)." Попробовал сейчас в VS98: // gh.cpp : Defines the entry point for the console application. // #include "stdafx.h" void g(int a1, int a2, int a3); template < class T1, class T2, class T3>void f(T1 &a1, T2 &a2, T3 &a3){ g(a1, a2, a3);} int main(int argc, char* argv[]) { f(1, 2, 3); return 0; } void g(int a1, int a2, int a3) { } Компилируется на ура! В общем вы слишком какие-то продвинутые вопросы обсуждаете... |
Сообщ.
#114
,
|
|
|
Первое: VS98 компилировать не умеет. Второе: VC98 (или MSVC98, если угодно) является инструментом 10-летней давности, который не удовлетворяет требованиям текущего стандарта, и проверять им код на соответствие текущему стандарту, согласись, по меньшей мере неразумно. Возми чё поновее и повтори попытку. Третье: это ещё не всё, твой код некорректен, т.к. не каждая g(), имеющая ровно 3 параметра, сможет быть вызвана вот такой вот твоей f(). Собственно это как раз и утверждалось в цитированном тобой фрагменте.
|
Сообщ.
#115
,
|
|
|
а какие компиляторы уже поддерживают стандарт?
|
Сообщ.
#116
,
|
|
|
Цитата maxutov @ а какие компиляторы уже поддерживают стандарт? А какой сейчас год? На второй странице говорилось следующее: Цитата archimed7592 @ К слову уже сейчас можно скачать расширения g++ для поддержки variadic templates, concepts. расширение vs-8.0 для поддержки template aliases и т.д. |
Сообщ.
#117
,
|
|
|
Цитата b-a1 @ Цитата maxutov @ а какие компиляторы уже поддерживают стандарт? А какой сейчас год? На второй странице говорилось следующее: Цитата archimed7592 @ К слову уже сейчас можно скачать расширения g++ для поддержки variadic templates, concepts. расширение vs-8.0 для поддержки template aliases и т.д. я имел ввиду беты много новых интересных вещей придумано в С++09 для приятного общения тестирование нужно проводить заранее |
Сообщ.
#118
,
|
|
|
maxutov, в этом плане, всё немного проще .
Даже текущий стандарт(2003 года) полноценно поддерживается разве что comeau и то, не знаю в какой степени... Что же касается будущего стандарта - во первых, неизвестно, когда его окончательно утвердят(т.е. провозгласят 14882 устаревшим, а 14883 "актуальным"), не говоря уже о полном соответствии современных компиляторов. |
Сообщ.
#119
,
|
|
|
Не могу не поделиться новостью. Оригинал здесь:
http://herbsutter.spaces.live.com/Blog/cns...B!785.entry На последнем заседании комитета по стандартизации среди всего прочего в стандарт C++0x включили поддержку lambda-функций. Полное описание можно прочитать в статье. Вкратце, новый стандарт будет допускать следующий код: Вывод коллекции на консоль: // Writing a collection to cout, in today's C++, option 2: copy( w.begin(), w.end(), ostream_iterator<const Widget>( cout, " " ) ); // Writing a collection to cout, in C++0x: for_each( w.begin(), w.end(), []( const Widget& w ) { cout << w << " "; } ); Поиск элемента в массиве: // Calling find_if using a functor, in today's C++: // outside the function, at namespace scope class GreaterThan { int weight; public: GreaterThan( int weight_ ) : weight(weight_) { } bool operator()( const Widget& w ) { return w.Weight() > weight; } }; // at point of use find_if( w.begin(), w.end(), GreaterThan(100) ); // Calling find_if using a lambda, in C++0x: find_if( w.begin(), w.end(), []( const Widget& w ) -> bool { w.Weight() > 100; } ); Алгоритмы как циклы: for_each( v.begin(), v.end(), []( Widget& w ) { ... ... use or modify w ... ... } ); transform( v.begin(), v.end(), output.begin(), []( const Widget& w ) -> AnotherType { ... return SomeResultCalculatedFrom( w ); } ); Выполнение кода в другом потоке: mypool.run( [] { cout << "Hello there (from the pool)"; } ); Также приняты в стандарт новый (альтернативный) формат объявления методов: direct-declarator: direct-declarator ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt exception-specificationopt -> type-id Т. е. позволяет задавать тип возвращаемого значения в конце объявления функции (что можно увидеть в приведенных выше фрагментах кода). Также позволили в объявлении функции использовать auto вместо типа возвращаемого значения. В этом случае тип функции был определен по типу возвращаемго значения в "самом последнем" операторе return. Чуть позже еще некоторые изменения опишу. |
Сообщ.
#120
,
|
|
|
Цитата Flex Ferrum @ На последнем заседании комитета по стандартизации среди всего прочего в стандарт C++0x включили поддержку lambda-функций. Хорошая новость! I λ... |