C производительность на глобальных переменных платы PIC по сравнению с локальным методом - PullRequest
1 голос
/ 07 февраля 2012

Все,

У меня есть функции C, которые вызываются много раз в секунду, поскольку они являются частью контура управления на плате PIC18.Эти функции имеют переменные, для которых требуется только область действия метода, но мне было интересно, что, если есть какие-либо издержки, это постоянное распределение этих переменных по сравнению с использованием глобальной или, по крайней мере, более высокой области действия.(Мысль о определении типа структуры для передачи из более широкой области видимости, чтобы избежать использования глобальной переменной, если производительность требует не использовать локальные переменные метода)

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

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

Что все думают?

Ответы [ 3 ]

2 голосов
/ 07 февраля 2012

Для доступа к локальной переменной требуется выполнить что-то вроде *(SP + offset) (где SP - указатель стека), тогда как для доступа к статической (которая включает глобальные переменные) требуется что-то вроде *(address).

Насколько я помню, набор команд PIC имеет очень ограниченные режимы адресации. Таким образом, весьма вероятно, что доступ к глобальному будет быстрее, по крайней мере, в первый раз, когда к нему обращаются. Последующие обращения могут быть идентичными, если компилятор хранит вычисленный адрес в регистре.

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

1 голос
/ 07 февраля 2012

Хотя я не использовал каждый существующий PIC-компилятор, существует два стиля. Стиль, который я использовал, статически распределяет все локальные переменные, анализируя граф вызовов программы. Если бы каждый возможный вызов был фактически выполнен, объем стековой памяти, потребляемой местными жителями, соответствовал бы тому, что потребовалось бы для статического выделения, с несколькими оговорками (описывающими поведение «стандартного» компилятора HiTech PICC-18 - другие могут отличаться )

  1. Функции Variadic обрабатываются путем определения хранилища локальных переменных в области действия caller и передачи двухбайтового указателя на это хранилище в вызываемую функцию.
  2. Для каждой другой сигнатуры косвенного указателя на функцию компилятор генерирует «псевдофункцию» в графе вызовов; все, что вызывает функцию этой сигнатуры, вызывает псевдофункцию, и эта псевдофункция вызывает каждую функцию с этой сигнатурой, для которой взят адрес.

В этом стиле компилятора последовательный доступ к локальным переменным будет таким же быстрым, как и последовательный доступ к глобальным переменным. Однако, кроме глобальных и статических переменных, явно объявленных как «ближние», которые должны составлять не более 64–128 байт (зависит от разных моделей PIC), глобальные и статические переменные для каждого модуля расположены отдельно от локальных переменных, и инструкции по смене банка необходимы для доступа к вещам в разных банках.

Некоторые компиляторы, которые я не использовал, используют опцию «расширенный набор команд». Эта опция поглощает 96 байтов «близкого» банка (или все это на PIC с менее чем 96 байтами) и использует его для доступа к 96 байтам относительно регистра FSR2. Это было бы замечательно, если бы в качестве фрейма стека использовались первые 16 или 32 байта. Использование 96 байтов означает отказ от всего «близкого» хранилища, что является довольно серьезным ограничением. Тем не менее, компиляторы, которые используют этот набор инструкций, могут обращаться к локальным переменным в стеке так же быстро, если не быстрее, чем глобальные переменные (не требуется переключение банков). Мне бы очень хотелось, чтобы у Microchip была возможность выделить только 16 байтов или около того для стекового фрейма, оставляя полезный объем оперативной памяти «общего банка», но, тем не менее, некоторым людям повезло с этим режимом.

0 голосов
/ 07 февраля 2012

Я полагаю, что это во многом зависит от того, какой компилятор вы используете.Я не знаю PIC, но я предполагаю, что некоторые (все?) Компиляторы PIC оптимизируют код так, чтобы по возможности локальные переменные сохранялись в регистрах ЦП.Если это так, то локальные переменные, вероятно, будут такими же быстрыми, как и глобальные.

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

...