Как уменьшить чрезмерное использование стека Lambda - PullRequest
2 голосов
/ 23 мая 2019

В настоящее время я работаю над проектом, который использует много лямбда-функций, и я обнаружил, что они используют много стека, но я не понимаю, почему. Я довольно новичок в C ++, я более привык к C.

Чтобы попытаться уменьшить использование стека и понять, как работает лямбда, я написал очень простой код, воспроизводящий наше использование лямбда-выражений. Я компилирую следующий код с опцией gcc и -Os.

typedef struct structTest
{
    uint32_t var1;
    uint32_t var2;
} structTest;

// Test 1
int main()
{
    dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );
}

// Test 2
int main()
{
    dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );

    dostuff( [&]() -> structTest{ structTest $; $.var2 = 13; $.var1 = 42; return $; }() );
}

Тест 1 использует 8 байтов стека, чего я не ожидал, но могу понять, но Тест 2 использует 16 байтов стека, и я не понимаю, почему. Я ожидал бы 8 байтов, так как в стеке, используемом для первого вызова функции, будет повторно использоваться для второго вызова.

Я бы предположил, что две структуры не будут зарезервированы в стеке.

Стек анализировали с помощью озона и использовали на Nucleo L476RG. Этот проект представляет собой проект IoT, в котором ПЗУ и стек являются ценными.

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

1 Ответ

1 голос
/ 23 мая 2019

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

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

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

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

Конечно, переработка или перегрузка dostuff, так что вы можете назвать это так:

dostuff(48, 24);

…будет лучше?

Реализация может быть такой простой, как:

__attribute__((noinline))
void doStuff(const uint32_t var1, const uint32_t var2)
{
   const structTest sT = {var1, var2};
   doStuff(sT);
}

Это также намного меньше кода и, IMO, легче читать.

КстатиХотя он работает на вашей платформе, я не рекомендую использовать $ в качестве идентификатора.Это нестандартно до степени и не очень понятно читателю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...