Существуют ли компиляторы, способные предлагать оптимизацию, которая абсолютно требует одобрения программиста?

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

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

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

Ошибки, предупреждения и ... предложения?

Компиляторы уже делают нечто подобное с «предупреждениями» в том смысле, что они объединяются в пул во время каждой компиляции и навсегда остаются в списке, пока вы не направите их к удовлетворению компилятора. Почему бы не иметь раздел «Предложения» или «Предлагаемые оптимизации», который функционирует аналогичным образом и потенциально может улучшить производительность вашего приложения?

Если компилятор должен был анализировать логические выражения на предмет сложности, предполагаемого времени выполнения, вероятности того, что отдельные операнды являются истинными или ложными и т. Д., То он мог бы создать список предложений, таких как лучший порядок для операндов выражений, и представить предложения. как список для программиста. Затем программист может обратиться к ним индивидуально и решить проигнорировать их или попросить редактор кода реализовать предложение.

Оптимизация порядка операндов логического выражения

Рассмотрим «Оптимизацию короткозамкнутых логических выражений». Поскольку порядок операндов влияет на то, какой операнд может быть «замкнут» (т.е. не вызван), порядок операндов в простых логических выражениях (например, A && B && C) - это то, что (я думаю) не затрагивается компилятором. чтобы избежать появления неизвестных побочных эффектов, если какой-либо операнд имеет побочные эффекты.

Учти это:

char c = reader.ReadChar(); //Stream bs; const string NEWLINE;
while (!IsStringPresent( c, bs, NEWLINE ) && c != ',')

Поскольку сравнение символа (быстрее / менее сложно), он должен стоять первым в выражении, чтобы логика короткого замыкания могла избежать вызова IsStringPresent при обнаружении запятой. Также верно, что в этом случае запятые (много на строку) будут встречаться чаще, чем последовательности новых строк.

char c = reader.ReadChar(); //Stream bs; const string NEWLINE;
if (c != ',' && !IsStringPresent( c, bs, NEWLINE )) //faster for short-circuit; plus ',' is encountered more often than newline

Резюме

Объективно, оптимальный порядок операндов может быть определен для любого выражения «A && B» на основе «Частота, когда A ложно по сравнению с B для запуска короткого замыкания» и «Стоимость вычислений A по сравнению с B, в пользу короткого замыкания большего количества дорогая ". Если компилятор мог определить приблизительные значения любого из них, во время компиляции, времени выполнения или обоих, то он мог бы определить, что конкретное выражение может быть неоптимальным, и он мог бы создать предлагаемое изменение для реализации программистом. .

Какие-нибудь компиляторы сегодня делают что-нибудь подобное? Если нет, то почему?


comment
Для вашего примера короткого замыкания проблема компилятора заключается в том, что IsStringPresent может иметь побочный эффект, которого НЕ было бы делать. Так что да, компилятор должен спросить. Придется составить список предположений, и вам придется его просмотреть. Когда этот список станет длинным, это станет источником ошибок: предположение меняется, вы не замечаете его в списке, это неверно, и теперь оптимизация идет плохо. И если вам придется записать ответ в виде набора нажатий клавиш, почему бы не сделать это, написав нажатия клавиш, которые изменяют порядок операндов самостоятельно?   -  person Ira Baxter    schedule 02.12.2011
comment
Что касается короткого замыкания в целом: то, что компилятор может сделать, - это решить, имеет ли вызываемая функция побочные эффекты на основе ее последней компиляции. Затем он может переупорядочить операнды на основе последнего результата компиляции и стоимости операций, как вы предложили.   -  person Ira Baxter    schedule 02.12.2011
comment
Во-первых, следует избегать побочных эффектов именно из-за короткого замыкания. Компиляторы перестраховываются, избегая изменения порядка операндов. Если программисты перестраховываются, как это часто предлагается, не включая скрытые обязательные побочные эффекты в наши сокращенные выражения, то переупорядочение операндов логически эквивалентным образом должно быть безопасным. Если это так, и это то, откуда я пришел ... тогда нам СЛЕДУЕТ оптимизировать этот порядок (действительно, ЧЕЛОВЕК должен решить), и я думаю, что компилятор может помочь нам, не усложняя его вообще.   -  person Triynko    schedule 02.12.2011
comment
Если компилятор знает, что вызываемые функции в выражении короткого замыкания действительно свободны от побочных эффектов, никаких дополнительных действий не требуется. Он может оценивать операнды в любом порядке, поэтому сначала следует выбрать самые дешевые. Вопрос в том, как компилятор узнает? а) вы утверждаете (возможно, ошибаетесь), б) компилятор проверяет вызываемую функцию, в) вы объявляете функцию свободной от побочных эффектов (FORTRAN чистый), и компилятор применяет ее.   -  person Ira Baxter    schedule 02.12.2011
comment
Компилятор не будет пытаться обнаружить побочные эффекты, это человеческая работа. Он рассмотрит такое выражение, как (A && B && C && D), посмотрите, какие OP являются лучшими короткозамыкателями (т.е., скорее всего, будут ложными), а также посмотрите на стоимость оценки каждого OP (простое сравнение против дорогих вызов функции) во время компиляции с точки зрения сложности, размера стека и т. д. Если выражение выглядит неоптимальным, то оно может профилировать фактические затраты на оценку времени выполнения и, наконец, предложить оптимальный порядок. Я не вижу ничего запутанного в том, чтобы сказать "Эй, (B && D && A && C) может быть более быстрым заказом!"   -  person Triynko    schedule 02.12.2011
comment
Но да, это то, что я говорю. Прямо сейчас мы думаем о правильном порядке и часто ошибаемся. Компилятор меня ни о чем не спрашивает, поэтому я знаю, что он даже не пытается помочь. Есть инструменты профилирования, но мы сами с ними. Разве не было бы замечательно, если бы эти инструменты были интегрированы вместе с нами, чтобы они были более автоматизированными и эффективными?   -  person Triynko    schedule 02.12.2011
comment
Здесь мы полностью согласны по модулю того, как компилятор узнает о побочных эффектах (следовательно, безопасность оптимизации). Сообщество компиляторов хорошо понимает, как переупорядочить бизнес с целью минимизировать время; действительно ли это в вашем компиляторе, решает ваш дружественный поставщик компилятора. Вы пробовали GCC, чтобы узнать, что он делает, если у вас есть несколько условий без побочных эффектов, некоторые со сложной арифметикой, а некоторые нет: например, какой код вы получаете с .... if (x ^ 10 ›y && y› 1 ) ...?   -  person Ira Baxter    schedule 02.12.2011


Ответы (3)


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

person Almo    schedule 01.12.2011
comment
О нет. Предполагается, что короткое замыкание ВСЕГДА происходит, например, в C #. Под решением, следует ли выполнить короткое замыкание, я имею в виду конкретный операнд, решая расположить его первым или вторым в выражении. Второе выражение будет сокращено, тогда как первое всегда вычисляется. - person Triynko; 02.12.2011
comment
Конечно, он будет проверять возможные оптимизации во время каждой компиляции и объединять их в список, как это происходит с предупреждениями компиляции. Если программист внесет предлагаемое изменение, то при следующей компиляции оно, очевидно, не будет обнаружено. В противном случае он мог бы просто так сидеть вечно, как сейчас предупреждения. - person Triynko; 02.12.2011
comment
Да, я говорю ... оптимизация выражений короткого замыкания заключается в определении наилучшего порядка операндов, помещая ПЕРВЫМИ операнды, которые являются самыми быстрыми / наиболее вероятными срабатываниями короткого замыкания. последние-операнды, и поместив ПОСЛЕДНИЕ операнды, которые работают медленнее / более желательны для короткого замыкания. - person Triynko; 02.12.2011

Мой ответ - «вероятно», но «действительно ли мы хотим этим заниматься?»

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

Моя мысль, однако, больше похожа на это: «Эй, программист, если бы мы могли это сделать, мы получили бы намного более быстрый код, однако семантика другая! Нам пришлось бы усилить предварительное условие этой функции, чтобы выполнить эту оптимизацию. . Это нормально?"

Усиление предварительного условия может быть нормальным, черт возьми, программист, вероятно, даже не написал предварительное условие. Если программисты говорят: «Конечно, все в порядке», а программист ошибается, то, если повезет, тестирование выявит проблему с «отказом предварительного условия».

person Yttrill    schedule 17.12.2011

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

Задача компиляторов - играть по стандартным правилам (насколько это возможно). Для некоторых (агрессивных) оптимизаций компиляторы предоставляют определенные флаги, которые можно передать для их включения / отключения, например. векторизация, встраивание, межпроцедурная и т. д. - эти оптимизации сложно выполнить вручную.

Переупорядочение (в приведенном вами примере) ограничено стандартами C, C ++, поскольку они могут изменить семантику программы. В случаях, когда операции не вызывают побочных эффектов, их можно переупорядочить, и компиляторы делают такие вещи во время планирования инструкций (при -O2 в clang ++ и g ++), но я не уверен, сколько других компиляторов это делают.

person A. K.    schedule 02.05.2013