#c #performance #memory-management #lambda
#c #Производительность #управление памятью #лямбда
Вопрос:
Выделение лямбды обходится дорого. В MSVC, когда я проверял последний раз, он выделяет ~ 128 байт. Это делает создание лямбд в цикле серьезной проблемой производительности.
В Python все литералы обрабатываются примерно так constexpr
, они вычисляются (при необходимости, как x = 10 * 25
), а затем кэшируются во время компиляции и просто заменяются там, где это необходимо.
Мне интересно, делается ли это на C , поскольку что-то вроде этого…
for (auto thing: things)
[](auto x){ /* do stuff */ }(thing);
… похоже, что он будет выделять лямбду несколько раз и, как будто, может использовать автоматическое кэширование, которое я описал выше.
Итак, это проблема производительности в C ? Было бы лучше сохранить лямбду в переменной перед циклом for и использовать эту переменную или все в порядке, как есть?
Комментарии:
1. Это, вероятно, будет чрезвычайно специфично для реализации. Однако обратите внимание, что лямбда-выражение без захвата требуется преобразовать в указатель на функцию. Под капотом это просто обычная функция. Вероятно, именно это и произойдет здесь. Однако вам придется проверить это самостоятельно.
2. в зависимости от контекста лямбда в C ведет себя как анонимная функция или как функциональный объект. В вашем странном примере это просто анонимная функция, поэтому с «КАК БУДТО правилом» компилятор имеет право оптимизировать это и удалить лямбду (тело лямбды станет частью
for
цикла).).3. Компиляторы, как правило, довольно умны, когда дело доходит до распределения локальных переменных, даже для динамических задач, таких как создание (но не хранение) объекта. Очень вероятно, что объектам, созданным внутри цикла, будет выделена память при входе функции или на первой итерации цикла. Тогда эта память будет использоваться повторно для каждого объекта, «созданного» внутри цикла. Вы можете проверить сгенерированный ассемблерный код, чтобы убедиться в этом поведении.
4. Не связано:
lambda
в python очень динамичный объект и будет выделять память каждый раз. (он должен фиксировать свое окружение)5. Во-первых: этот лямбда-код не захватывает
thing
, и, очевидно, если вы захватите 128 байт, то лямбда-код займет более 128 байт. В дополнение к замечаниям @Someprogrammerdude, компиляторы, которые могут использовать данные профилирования, могут работать еще лучше. Они могут проверить, существуют ли фактические шаблоны потока, и посмотреть, требуется ли выделение лямбды при каждом вызове функции (поэтому просто увеличьте фрейм стека) или только иногда (сделайте эквивалентalloca
. ).
Ответ №1:
Поскольку ваш лямбда-код не захватывается и вызывается немедленно, любой достойный компилятор переведет лямбду в статическую функцию и встроит вызов с нулевыми накладными расходами.
Вы уверены, что не путаете лямбды с std::function
?