2016-11-12 5 views
2

Я борюсь со следующей проблемой производительности при компиляции C++ для небольшого ARM-процессора с использованием компилятора ARM/Keil.Как предотвратить выделение объектов, объявленных как локальные переменные в стеке?

Внутри функция, которая делает некоторую обработку у меня есть код со следующей структурой:

{ 
    MyClass temp = global_variable_input; 

    Operation 1 on temp; 
    Operation 2 on temp; 
    ... 
    Operation N on temp; 

    global_variable_output = temp; 
} 

МойКласса используется для моделирования математического объекта и единственный элемент представляет собой 32-битное целое число (то есть, полного размер объект - 4 байта).

Все операции включают использование перегруженного оператора или метода MyClass и изменение значения «temp» в результате. Некоторые операции тривиальны и встроены (метод объявлен inline в классе), а некоторые более сложны и требуют вызова метода.

Имея взгляд на код ассемблера, сгенерированный компилятором для моей подпрограммы, я заметил, что компилятор выделяет пространство для «temp» в стеке, и каждая операция (также встроенные) хранит результат операции в это место в стеке, чтобы затем продолжить использование значения, хранящегося в регистре, из последней операции. Для неединичных, компилятор передает указатель на объект (этот) в регистр r1 и указатель на другой объект, созданный в стеке, чтобы сохранить результат в регистре r0.

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

В идеале я ожидал, что компилятор завершит операцию, используя только регистр, вместо хранения сложной версии «temp», которая должна обновляться после каждой операции.

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

Я прошу слишком много? Как я могу заставить мой компилятор ARM/Keil работать таким образом?

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

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

+0

Как насчет 'MyClass & temp = global_variable_input;'? ' –

+3

Вы пробовали с разными уровнями оптимизации? – Macmade

+0

Спасибо за предложение! Я попробую ссылку. Но я могу себе представить, что компилятор будет еще более оправданно обновлять значение после каждой операции? (Так как теперь это ссылка на глобальную переменную, а кто-то другой ее может использовать) – MrDoe

ответ

1

Использование ссылки как

MyClass& temp = global_variable_input; 

бы избежать полной копией MyClass выделяется в стеке (локальное хранилище)

Хотя любой из

Operation 1 on temp; 
Operation 2 on temp; 
// ... 

влияют на оригинальные global_variable_input также.

+1

К сожалению, моя проблема с производительностью все равно останется. – MrDoe

-2

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

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