2010-01-06 3 views
9

Я только что задал вопрос, связанный с тем, как компилятор оптимизирует определенный C++ code, и я оглядывался по всем вопросам о том, как проверить, что компилятор выполнил определенные оптимизации. Я пытался посмотреть сборку, созданную с помощью g ++ (g++ -c -g -O2 -Wa,-ahl=file.s file.c), чтобы увидеть, что происходит под капотом, но вывод слишком загадочен для меня. Какие методы используют люди для решения этой проблемы, и есть ли хорошие ссылки на то, как интерпретировать списки сборок оптимизированного кода или статей, специфичных для инструментальной цепочки GCC, которые говорят об этой проблеме?Проверка оптимизации компилятора в gcc/g ++ путем анализа списков сборок

+5

Я бы не стал пытаться интерпретировать оптимизированный код, если вы не пишете оптимизацию.Вы обязательно потеряете рассудок. Существует большая стоимость времени, затрачиваемая на обучение самому расшифровать оптимизированную сборку. –

+0

Похожа: http://stackoverflow.com/questions/1121032/detect-if-c-binary-is-optimized –

+0

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

ответ

3

Не gcc, но при отладке в Visual Studio у вас есть возможность сгруппировать сборку и источник, что дает хорошее представление о том, что было создано для какой инструкции. Но иногда это не совсем правильно.

Выход цепочки инструментов gcc и objdump -dS не имеет одинаковой детализации. This article при получении gcc для вывода источника и сборки имеют те же параметры, что и вы.

+0

Вы можете использовать вкрапленные сборки и код при компиляции с оптимизацией? Я помню, как однажды возникла проблема с этим. –

+0

У меня нет оконной машины, где я нахожусь в данный момент, поэтому не могу подтвердить, но не помню, чтобы это было проблемой. –

+0

Да, он работает даже при оптимизации. Разумеется, теперь нет более строгого сопоставления 1 к 1, но компилятор все же делает все возможное, чтобы пересечь исходный код, и в целом он работает очень хорошо. – jalf

18

Оптимизация GCC проходит работу над промежуточным представлением вашего кода в формате GIMPLE.

Используя -fdump-* family of options, вы можете попросить GCC вывести промежуточные состояния дерева.

Например, кормить это gcc -c -fdump-tree-all -O3

unsigned fib(unsigned n) { 
    if (n < 2) return n; 
    return fib(n - 2) + fib(n - 1); 
} 

и смотреть, как она постепенно превращается из простого экспоненциального алгоритма в комплексное полиномиальный алгоритм. (Действительно!)

+1

Это аккуратный трюк. Если бы я понял выход! –

+1

+1 coooooooooooooooool! – James

0

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

Что касается общего вопроса, я читал (и писал) язык ассемблера более чем (gulp!) 30 лет, и все, что я могу сказать, это то, что он принимает практику, особенно для чтения вывода компилятора.

0

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

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

2

Добавление опции -L (например, gcc -L -ahl) может предоставить несколько более понятные списки.

Эквивалентная опция MSVC: /FAcs (и это немного лучше, потому что она перемежает исходный, машинный язык и двоичный файл и включает некоторые полезные комментарии).


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

Блоги и статьи для разработки игр могут быть хорошим ресурсом для этой темы, поскольку игры - это приложения реального времени в постоянной памяти - I have some notes on it, также Mike Acton и другие. Обычно я люблю держать Intel's instruction set reference в окне, просматривая списки.

Самое полезное заключается в том, чтобы вначале получить хорошее наземное понимание программирования сборки - не потому, что вы хотите написать код сборки, а потому, что, сделав это, значительно упростите чтение. У меня был a hard time finding хороший современный учебник.

+0

Я не нахожу '-L' или' -ahl' эффект, описанный в руководстве GCC. –

+0

Ваша последняя ссылка отсутствует. – edmz

4

Полезным методом является запуск кода под хорошим профилировщиком пробоотбора, например. Zoom под Linux или Instruments (с инструментом Time Profiler) в Mac OS X. Эти профилировщики не только показывают вам горячие точки в вашем коде, но также и исходный код карты для дизассемблированного объектного кода. Выделение строки источника показывает (не обязательно смежные) строки сгенерированного кода, которые сопоставляются с исходной строкой (и наоборот). Онлайн-ссылки на опкод и советы по оптимизации - прекрасный бонус.

+2

Zoom (http://rotateright.com) также может статически анализировать двоичный файл ELF, поэтому вам даже не нужно запускать/профайлировать код, чтобы просто убедиться, что компилятор сгенерировал ожидаемый asm. – XWare

+1

@XWare: хорошая точка - и Shark на Mac OS X также обладает этой возможностью –

1

Увеличить из RotateRight (http://rotateright.com) упоминается в другом ответе, но и расширить на что: он показывает отображение источника для сборки в том, что они называют «браузер кода». Это невероятно удобно, даже если вы не эксперт по asm, потому что они также интегрировали сборку документации в приложение. И список сборок аннотируется комментариями и сроками для нескольких типов ЦП.

Вы можете просто открыть свой объект или исполняемый файл с помощью Zoom и посмотреть, что компилятор сделал с вашим кодом.

1

для вывода оптимизаций применяется вы можете использовать:

-fopt-инфо оптимизированной

Чтобы увидеть те, которые не были применены

-fopt- info-missed

Опасайтесь, чтобы выход i ы отправлены в стандартный поток ошибок так, чтобы увидеть его вы на самом деле нужно перенаправить что: (подсказка 2> & 1)

Вот хороший пример:

g++ -O3 -std=c++11 -march=native -mtune=native 
     -fopt-info-optimized h2d.cpp -o h2d 2>&1 

h2d.cpp:225:3: note: loop vectorized 
h2d.cpp:213:3: note: loop vectorized 
h2d.cpp:198:3: note: loop vectorized 
h2d.cpp:186:3: note: loop vectorized 

Вы можете проверить с чередованием вывод, когда приложил -g с objdump -dS|c++filt, но это не поможет вам в этом. Наслаждайтесь!

Смежные вопросы