Как подсчитать, сколько раз использовалась глобальная переменная (чтение и запись)?

Я пытаюсь оптимизировать проект кода C.

Я хотел бы подсчитать, сколько раз глобальная переменная использовалась (чтение или запись), чтобы поместить ее в наиболее подходящий тип памяти.
Например, чтобы хранить часто используемые переменные в памяти быстрого доступа.

Кэш данных отключен по детерменистическим причинам.

Есть ли способ подсчитать, сколько раз использовалась переменная, не вставляя счетчики и не добавляя дополнительный код? например, используя ассемблерный код?

Код написан на Си.

В моем распоряжении:

A) Файл (.map), сгенерированный компилятором GCC, из которого я извлекаю имена, адреса и размеры глобальных переменных.

Б) Ассемблерный код проекта, сгенерированный с использованием флага -S компилятора GCC.

Большое спасибо,


person ZivYam    schedule 20.06.2019    source источник
comment
Зачем тебе это, еще раз? Чтобы правильно разместить его в памяти? Если это так, я боюсь, что вы не можете сделать это, используя простой C. Вам придется использовать встроенные функции компилятора и/или скрипт компоновщика. Кроме того, компилятор неправильно выделяет память для этой переменной? Потому что этого не может быть, если вы не используете специально созданный компилятор или что-то в этом роде. В любом случае это также не должно давать значительного прироста производительности.   -  person ForceBru    schedule 20.06.2019
comment
На какую архитектуру вы ориентируетесь?   -  person user58697    schedule 20.06.2019
comment
Идея состоит в том, чтобы хранить часто используемые переменные в памяти с быстрым доступом (кэш данных отключен по детерменистическим причинам).   -  person ZivYam    schedule 21.06.2019


Ответы (3)


В GDB есть так называемые точки наблюдения: https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html

Установите точку наблюдения для выражения. GDB сломается, когда выражение expr будет записано программой и его значение изменится. Самое простое (и самое популярное) использование этой команды — просмотр значения одной переменной:

(gdb) смотреть фу

awatch [-l|-местоположение] expr [идентификатор потока потока] [значение маски маски]

Установите точку наблюдения, которая будет прервана, когда expr считывается или записывается программой.

К точкам наблюдения можно прикрепить команды: https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html#Break-Commands

Вы можете назначить любой точке останова (или точке наблюдения, или точке перехвата) ряд команд, которые будут выполняться, когда ваша программа остановится из-за этой точки останова... Например, вот как вы можете использовать команды точки останова для вывода значения x при входе в foo всякий раз, когда x положительный.

break foo if x>0 
commands 
silent 
printf "x is %d\n",x 
cont 
end

Команда обычно должна увеличивать переменную или печатать «чтение/запись» в файл, но вы действительно можете добавить и другие вещи, например, обратную трассировку. Не уверены в лучшем способе внешней связи с помощью gdb. Может быть, вам достаточно запустить его в интерактивном режиме.

person Andreas    schedule 21.06.2019

Вы можете сделать это, используя Visual Studio (или другую IDE): найдите все места, где ваша переменная используется в исходном коде, поставьте условную точку останова, зарегистрируйте некоторую информацию, присоединитесь к процессу и запустите функции, которые используют эту переменную. . Вы можете подсчитать экземпляры в окне вывода.

person Dominique    schedule 21.06.2019

Я думаю, вам нужна автоматическая инструментация и/или профилирование. GCC может сделать для вас оптимизацию по профилю. Помимо других инструментов, в документации даже упоминается хук для реализации собственного пользовательского инструментария.

Существует несколько инструментов анализа производительности, таких как профилировщики perf и gprof.

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

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

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

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

person Vladislav Ivanishin    schedule 21.06.2019