All streams
Search
Write a publication
Pull to refresh
26
0
Ануфриенко Андрей Владимирович @andrei_an

User

Send message
Конечно есть. Просто это будет неэффективно в смысле производительности, поэтому если в приведенном тесте поставить #pragma ivdep, то компилятор сообщит, что векторизация возможна, но неэфективна и придется добавить #pragma vector always, чтобы заставить компилятор делать векторизацию несмотря на его сомнения. Автовекторизатору придется потратить массу усилий на формирование векторов.
Тут, к сожалению, действительно много проблем. Если говорить о цикловых оптимизациях, то компилятор с -O2 и -O3 активно вмешивается в действия программиста и стремится все переиначить на свой лад и как добиться сохранения своего варианта — не понятно. Часто попытка делать цикловые оптимизации самому приводит к плачевным результатам.
Вот и в данном эксперименте хорошим заключительным аккордом было бы заставить компилятор завекторизовать оптимизированные мною циклы и сравнить результат с векторизованным результатом компилятора. Но у меня не получилось. Векторизация тоже цикловая оптимизация и включается только вместе с остальными.
Поскольку я начал про цикловые оптимизации, то следующим шагом хочется расказать немного о зависимостях, как главной проблеме для компилятора при выполнении цикловых оптимизаций и сопутствующих проблемах, таких как разрешение неоднозначности при работе с памятью и т.д. Потом хочется рассказать о векторизации, автопараллелизации,… Да profile guided оптимизации есть вэтом списке, но до них вряд ли дело скоро дойдет :)
В интеловском компиляторе сейчас два режима работы ipo. В первом случае с -Qipo создаются объектные файлы, которые содержат упакованное внутреннее представление. Во время второй фазы компилятор читает все эти файлы, строит граф вызовов, делает межпроцедурный анализ, затем межпроцедурные оптимизации и WPA (если удается доказать что работаем с полной программой) и затем уже все процедуры обрабатываются (различные скалярные и цикловые оптимизации) и создаются файл ipo.obj (или несколько ipo_n.obj). Второй вариант используется с -Qip. В этом случае межпроцедурный анализ работает с одним исходным файлом и делает оптимизации на основе того графа вызовов, который удается построить. Первый вариант должен давать лучшие результаты, но второй часто используется, поскольку он менее требователен к ресурсам.
5.) Наверное, это все же вопрос терминологии. WPA оптимизации ведь тоже применяются на графе вызовов и связаны с глобальной протяжкой разной информации с использованием этого графа. Т.е. если считать работу с графом вызовов IP работой, то WPA просто специализированные межпроцедурные оптимизации (оптимизации на графе вызовов) учитывающие важный дополнительный фактор.
Но вообще, я согласен с этим замечанием и буду впредь разделять эти два вида оптимизаций.
3.) Я это понимаю и не вкладывал во фразу «не нужно определять детальный порядок» смысл, что планирование инструкций — это просто. В дальнейшем я упоминаю планирование как важную оптимизацию.
4.) Хорошо, объединие регистров и подсистемы памяти неудачное, поскольку методы разрешения проблем с кэшем и регистрами совершенно разные.
7.) В некоторых случаях я так и делаю, но и частое использование оригинальных терминов не украшает текст.
Спасибо. Действительно, логичнее использовать термин шина памяти.
Векторизация не всегда применима. К тому-же и для векторизованного цикла тоже можно сделать unroll. Так-же существует полная развертка небольших циклов с известным количеством итераций — исключительно полезная оптимизация. Как раз при векторизации часто возникают такие циклы. Поэтому развертка активно используется.
1.) Если открыть, например, Intel® 64 and IA-32 Architectures Software Developer’s Manual, то там в разделе Basic Architecture понятие System Bus активно используется, как механизм соединяющий вычислительное ядро с памятью и остальным процессором. В этом виде этот термин меня вполне устраивает. Могли бы вы объяснить, какой, на ваш взгляд, термин нужно использовать и почему?
2.) Суперскалярность — это наличие нескольких исполняющих устройств. В данном случае описан механизм выбоки из буфера просмотра инструкций на обработку (То что вы в своем следующем вопросе называете определенным окном). В случае in order, насколько я понимаю, нет необходимости просматривать какие-то буфера и что-то выбирать, инструкции поступают на обработку в порядке определенном кодогенератором.
3.) Именно этот механизм здесь и описан. «Не нужно определять детальный порядок» и означает, что планированием инструкций нужно заниматься ориентируясь на буфер просмотра (look-ahead buffer). По идее механизмы внеочередного выполнения команд должны примерно одинаково отработать если инструкции будут перемешаны в пределах этого буфера. Наверное, в реальности все несколько сложнее, но идея такая.
4) Рассматривается не кэш, а качество работы подсистемы памяти и регистры туда включены на правах самой быстрой памяти.
5) В соответствии с моими представлениями, именно в процессе межпроцедурного анализа определяется имеет ли компилятор дело с полной программой или каким-то неполным графом вызовов. В случае если компилируется полная программа включаются дополнительные межпроцедурные оптимизации и делается более качественный межпроцедурный анализ. То есть из моей практики не следует, что это очень разные вещи. Действительно при компиляции неполной программы сужается набор возможных оптимизаций.
6) Спасибо за информацию. Но не вижу теоритически никаких препятствий для векторизации vector. То, что он не векторизуется или скорее векторизуется при выполнении сложных условий является недостатком компилятора. Посмотрю как компилятор справляется с valarray.
7) А я планирую развивать тему, поэтому двигаюсь планомерно.Спорные переводы возникают во многом оттого, что есть некий недостаток в справочной информации в Интернете. Описания идей многих оптимизаций присутсвуют только на английском как и практически вся используемая мной техническая литература.
Спасибо за критику.
Так «неконкретное» поведение компилятора характерно практически для каждой оптимизации. Сначала нужно доказать, что оптимизацию можно делать. Доказательство может быть сложным и требовать много ресурсов, поэтому в любой момент компилятор может отказаться от дальнейшего исследования и отказаться от оптимизации. Далее нужно как-то оценить выгоду от оптимизации. И здесь может быть много факторов. Если взять для примера автовекторизатор, то он может сообщить о зависимостях, о плохой структуре цикла, о том что векторизовать невыгодно и т.д. В результате спрогнозировать, какие оптимизации будут применены в том или ином случае достаточно сложно.
Компиляторные оптимизации действительно работают часто как дополнительный бонус и многих это устраивает.
В чем магия-то? В том что нужно проверить все исходные файлы и убедиться что поля структуры всегда адресуются через их имена и никогда через указатели с какими-нибудь офсетами?
Думаю PGO и использование динамического профилировщика здесь действительно необходимо, потому что оценить частоту использования полей с помощью статического профилировщика проблематично, хотя в каких-то вырожденных случаях (поля вообще не используются) такое в принципе возможно.
Спасибо за вопрос.
Ну если выше не конкретика, то я пас.
Про ограничения я написал.
И Да! Мы здесь в Intel делаем чудеса :)
Хотя чудес я тут не вижу. Нужно посмотреть какие-то конкретные примеры и оценить область применимости данных оптимизаций. Она, скорее всего достаточно узкая.
Согласен. Тул при анализе полезен и во многих случаях хорошо помогает. Но он очевидно не панацея и делать какие-то далеко идущие оценки без анализа приложения довольно бесперспективно.
Есть в интеловском компиляторе такой набор опций — Qprof_use и -Qprof_gen. С этими опциями компилятор сначала делает инструментированный код, затем собирается статистика про выполнение приложения (тестовые прогоны) и на основе сбора этой статистики приложение еще раз пересобирается с ее учетом. Понятно, что приложение должно гоняться на представительном наборе данных. Тогда появляется возможность оценить вес использования тех или иных полей. Компановка вместе наиболее часто используемых полей должна снижать нагрузку на шину данных. Плюс к этому, наверняка, должна быть включена межпроцедурная оптимизация, чтобы проверить, что поля можно двигать. Как-то так, если коротко.
А если длинно, то нужно сделать отдельный пост по этой теме.
Про другие компиляторы не скажу — не изучал вопрос.
Удовлетворяет такой ответ?
Ну я думаю вы сильно ошибаетесь в оценках полезности таких оптимизаций для производительности. Я надеюсь приведу в будущем пару примеров, которые вас удивят.
Не вижу никакой сложности в изменении порядка полей в структуре.
Компилятор умеет делать такие оптимизации, но здесь сложно бывает доказать именно корректность. Руками программист может все делать гораздо эффективнее, но для этого нужно понимать, на что такие модификации влияют.
Не совсем — скорее наоборот.
Если спортсмен бежит с полным напряжением сил по длинной дороге, то он в итоге может уступить и черепахе, идущей коротким путем.
Вы так оставите без работы массу людей, которые пишут умные книги типа «Optimization compilers for modern architectures». Они, наивные, используют в своей жизни детский принцип «Если мама не увидит, это маму не обидит» :)
На самом деле никакого противоречия с бинарной совместимостью не возникает, поскольку все такие оптимизации делаются при создании исполняемого файла при наличии полного набора исходников. В объектных файлах и библиотеках вы ничего подобного не увидите.
Согласен. В рамках языка Cи много легальных вещей, которые осложняют жизнь компиляторам да и самим разработчикам. Иногда даже вводяться правила типа ansi_alias rules, чтобы ограничить креативность разработчиков. Задача компилятора сделать консервативный анализ, то есть доказать, что та или иная оптимизация корректна и не изменяет результаты работы приложения.
Нужно обращаться сразу с претензиями к Spec.org. Они делают перечисленные вами неэтичные вещи и постоянно сравнивают коды полученные с помощью разных компиляторов на разных вычислительных архитектурах. Да еще деньги за это получают.
Понятно, что разные компиляторы делают разные наборы оптимизаций с одним и тем-же набором опций, но в данном случае сравнение компиляторов — вовсе не тема данной статьи.
Собственно, я мог бы сравнит «старушку» VS2010 c каким-нибудь «древним» интеловским компилятором. Но результата это бы не изменило, поскольку автовекторизатор в интеловских компиляторах появился давно, а в VS только в VS2012.
Открою вам тайну, есть много людей, которые полагают, что Microsoft скрывает важную информацию об устройстве своих операционных систем.
Почему вы ограничиваете меня в инструментах по познанию мира :)?
Если вы не планируете отлаживать свое приложение, ставите максимальный уровень оптимизации, то для компилятора нет никаких ограничений в используемых трансформациях вашего кода, кроме выдачи в итоге верного результата. Понятно, если вы обращаетесь к элементам вашей структуры каким-нибудь хитрым способом через офсеты и указатели, то компилятор должен заметить ваш высокий проффесионализм и понять что ему лучше здесь отдыхать и не вмешиваться.

Information

Rating
Does not participate
Location
Новосибирская обл., Россия
Date of birth
Registered
Activity