На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (77) « Первая ... 6 7 [8] 9 10 ...  76 77  ( Перейти к последнему сообщению )  
> Текущий Стандарт С++ и перспективы его развития
    Славян и другие
    Не вижу смысла пользоваться такими заумными конструкциями. Если ты знаешь, что там ноль, то так и пиши =0, нечего компилятору голову морочить, и тем кто потом программу читать будет (в основном им).
      Славян
      Цитата Славян @
      2.Это не оптимизатор считает что-то нужным, а люди думают, сколько они сил готовы потратить, чтобы усилить оптимизатор. И часто махают рукой.
      Вот когда ты будешь обладать не меньшим количеством информации, чем оптимизатор, тогда ты сможешь считать, что усиливаешь его. Заметь, он обладает куда бОльшей информацией о сгенерированном коде, чем ты, рассматривая ассеблерный листинг вблизи места предполагаемого вмешательства. А пока ты не доказал, хотя бы себе, что:
      • уменьшив длину одной инструкции, учёл влияние этого при их выборке из кеша;
      • сможешь конкурировать с оптимизатором в прогнозировании драк за строки кеша данных и в предсказании переходов и следовательно более грамотно, чем он, сможешь расставить обращения к памяти в теле циклов и развернуть их в оптимальное количество раз;
      • в ассеблерных вставках сможешь грамотно переупорядочить порядок инструкций для исключения простоя декодеров и полноценной загрузки конвейеров и исполнительных блоков процессора и исключения их чрезмерных простоев;
      • итп
      считай, что ты оптимизатору будешь только мешать, ибо он тебя послушается даже в ущерб своей задаче. Даже выиграв локально тут, в целом можешь проиграть крупнее где-нибудь там, и не заметить этого.
      Сообщение отредактировано: Qraizer -
        Qraizer, все это замечательно. Только здесь же в холиварах ассемблерщики показывают, что оптимизатор (практически во всех перечисленных тобою пунктах) сливает проф. ассемблерщику. Т. е. я хочу сказать, что какие-то оптимизаторы, может быть, и умеют оптимизировать так, как ты описал, но таких - единицы. И те же компиляторы от Intel и Microsoft такими свойствами не обладают. Если считаешь иначе, прошу вот в эту: http://forum.sources.ru/index.php?showtopic=209970 тему.
          Чесговоря, не нашёл я в этом топике того, что ты мне хотел показать. Читал не весь - большой уж больно - так что ткни меня носом конкретнее, плз. Либо я не понял, чтО ты хотел мне показать. Я подумал что "ассемблерные профессионалы, затыкающие оптимизаторы без особых усилий - это не редкость". Так что проясни, если не трудно.
          Далее. Оптимизаторы, которые я имел в виду, отнюдь не редкость. Только надо предоставить им достаточно информации для работы. Например, размеры строк кеша зависят от процессора, поэтому пока не укажешь оптимизатору каким-нибудь ключиком /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. Вот пишу сейчас и думаю, нафиг я на это потратил столько времени? Разве что здесь похвастаться, а так практического эффекта никто не заметил и никогда не заметит. Да и было это один-единственный раз за последние лет восемь.
          В общем, мне это неинтересно, я лучше найду более другие причины потратить своё рабочее время. С пользой в сторону переносимости, гибкости, масштабируемости и надёжности. Если у кого другое ИМХО, да пожалуйста. Только для предотвращения воизбежания пусть почитает обо всём этом тут, ну а там пусть делает свои выводы и поступает сообразно им. Да и не всем "двигать мировую экономику и внедрять демократию", кому-то надо "...быть спортсменом или клоуном, чтоб политики и демократы могли иногда отдохнуть от подгаживания своим коллегам и расслабиться под зрелище смачной драки футбольных фанатов или там резню гладиаторов..." © Гай Юлий Орловский.
          Сообщение отредактировано: Qraizer -
            Блин, как всё сложно. Просто, поверите ли нет, ну дураку понятно, что код вида :
            ExpandedWrap disabled
              mov edi, edi
              push ebp
              mov ebp, esp
              mov eax, [eax+$xxyyzzww]
              pop ebp
              ret

            // вроде User32.dll
            или вида
            ExpandedWrap disabled
              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-примера( когда нефиг напрягаться компилятору за стэк), очевидно глупее моих :
            ExpandedWrap disabled
              mov eax, [eax+$...]
              ret

            Мне не нужно изучать кэши и промахи в него, ибо я суть оптимизатора вижу. И уж поверьте хоть и смотрю 'листинг вблизи места', вижу больше, чем он.

            Ну на кой ляд делать код
            ExpandedWrap disabled
              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
              Мда, маловаты у тебя фрагменты, как-то ты черезчур буквальНо поспринял слово "вблизи". Так что на безгрешность не претендую, однако...
              С первым примером для меня всё ясно. Первая инструкция - это двухбайтный ноп. Для чего он там - это вопрос уже не ко мне. Даже после самых дерьмовых оптимизаторов просто так нопы никогда не остаются, т.е. к оптимизации он не имеет прямого отношения. Игра со стековым фреймом - так без него плохо живётся всяким там отладчикам, профайлерам, кодековерам итп. А экспортируемые функции без стекового фрейма - это вообще нонсенс. Менеждер виртуальной памяти может это не одобрить по полной программе. Вообще же, ставишь галку компилеру, и он напрочь забывает о фреймах. И наоборот: не поставил галку - компилятор обязан создавать фреймы. Что, скажешь ни разу этой галкой не пользовался? Что-то я не пойму твоего недовольства этим фрагментом.
              Второй фрагмент вполне оптимален. Наверняка компилятору было сказано ключиком, чтобы он использовал строгое соответствие стандарту 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 напомнил, инициализация присваиванием и твоя логической операцией нагружают разные исполнительные блоки процессора. Именно поэтому иногда оптимизаторы используют твою идею, иногда нет. Нагружает так, чтобы получилось поравномернее, а если в данном кокретном случае пофигу, то просто юзают "прямой" способ.
              Сообщение отредактировано: Qraizer -
                Вы когда спорите со Славяном, держите в уме вот это: Определить бинарный файл (сообщение #1816742) и вот это: Определить бинарный файл (сообщение #1817916) :)
                  Я только начинаю учить шаблоны :) поэтому мне не очень понятно тут все :) В первом сообщении думал -
                  Цитата
                  что текущий стандарт, для заданного выражения E(a1,a2,...,aN), которое зависит от параметров a1,a2,...,aN, не позволяет написать такую ф-цию(или функтор), которая будет эквивалентна этому выражению.

                  Думаю как это так? Ну например a1+a2+a3. Почему нельзя сделать функцию с параметрами a1,a2,a3, в которой будет строчка return a1+a2+a3?

                  Потом идет первый пример - где "Всё бы хорошо, но нельзя сделать вызов f(1, 2, 3)."

                  Попробовал сейчас в VS98:

                  ExpandedWrap disabled
                    // 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)
                    {
                    }


                  Компилируется на ура! В общем вы слишком какие-то продвинутые вопросы обсуждаете...
                    Первое: VS98 компилировать не умеет. Второе: VC98 (или MSVC98, если угодно) является инструментом 10-летней давности, который не удовлетворяет требованиям текущего стандарта, и проверять им код на соответствие текущему стандарту, согласись, по меньшей мере неразумно. Возми чё поновее и повтори попытку. Третье: это ещё не всё, твой код некорректен, т.к. не каждая g(), имеющая ровно 3 параметра, сможет быть вызвана вот такой вот твоей f(). Собственно это как раз и утверждалось в цитированном тобой фрагменте.
                    Сообщение отредактировано: Qraizer -
                      а какие компиляторы уже поддерживают стандарт?
                        Цитата maxutov @
                        а какие компиляторы уже поддерживают стандарт?

                        А какой сейчас год? :rolleyes:

                        На второй странице говорилось следующее:
                        Цитата archimed7592 @
                        К слову уже сейчас можно скачать расширения g++ для поддержки variadic templates, concepts. расширение vs-8.0 для поддержки template aliases и т.д.
                        :)
                          Цитата b-a1 @
                          Цитата maxutov @
                          а какие компиляторы уже поддерживают стандарт?

                          А какой сейчас год? :rolleyes:

                          На второй странице говорилось следующее:
                          Цитата archimed7592 @
                          К слову уже сейчас можно скачать расширения g++ для поддержки variadic templates, concepts. расширение vs-8.0 для поддержки template aliases и т.д.
                          :)

                          я имел ввиду беты
                          много новых интересных вещей придумано в С++09 для приятного общения
                          тестирование нужно проводить заранее
                          Сообщение отредактировано: maxutov -
                            maxutov, в этом плане, всё немного проще :).
                            Даже текущий стандарт(2003 года) полноценно поддерживается разве что comeau и то, не знаю в какой степени... Что же касается будущего стандарта - во первых, неизвестно, когда его окончательно утвердят(т.е. провозгласят 14882 устаревшим, а 14883 "актуальным"), не говоря уже о полном соответствии современных компиляторов.
                              Не могу не поделиться новостью. Оригинал здесь:
                              http://herbsutter.spaces.live.com/Blog/cns...B!785.entry

                              На последнем заседании комитета по стандартизации среди всего прочего в стандарт C++0x включили поддержку lambda-функций. Полное описание можно прочитать в статье. Вкратце, новый стандарт будет допускать следующий код:
                              Вывод коллекции на консоль:
                              ExpandedWrap disabled
                                // 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 << " "; } );


                              Поиск элемента в массиве:
                              ExpandedWrap disabled
                                // 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; } );


                              Алгоритмы как циклы:
                              ExpandedWrap disabled
                                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 );
                                } );


                              Выполнение кода в другом потоке:
                              ExpandedWrap disabled
                                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.

                              Чуть позже еще некоторые изменения опишу.
                                Цитата Flex Ferrum @
                                На последнем заседании комитета по стандартизации среди всего прочего в стандарт C++0x включили поддержку lambda-функций.

                                Хорошая новость!
                                I :wub: λ...
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (77) « Первая ... 6 7 [8] 9 10 ...  76 77


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0553 ]   [ 16 queries used ]   [ Generated: 23.04.24, 13:58 GMT ]