#c #gcc #optimization #lambda #clang
#c #ссагпз #оптимизация #лямбда #clang
Вопрос:
Рассмотрим слегка измененную версию Фибоначчи, чтобы проверить производительность между (лямбда-функцией и функцией) (с и без) захватами:
size_t fibFn(size_t n) {
if (n <= 1) { return n; }
return fibFn(n - 1) fibFn(n - 2) 1 2;
// ^~~~
// This is modified so that I can |
// capture something outside |
// this function |
}
Когда я запустил это в Quickbench с Clang 10.0, я получил разумный результат:
fnNoCapture < лямбдаНоКаптура < fn << лямбда
Однако, когда я только собираюсь сделать вывод, что лямбда-выражение с блоком захвата работает чрезвычайно медленно, результат почти полностью инвертируется, когда я запускаю это с помощью GCC 10.1:
lambdaNoCapture > fnNoCapture >> fn > лямбда
Как это возможно? Это потому, что два компилятора реализовали lambda по-разному?
РЕДАКТИРОВАТЬ: Тем не менее, для меня не имеет смысла, что лямбда-выражение (с захватом) может быть намного быстрее, чем без захвата. Лучший случай, который компилятор может оптимизировать, на мой взгляд, — это преобразовать лямбда-выражение с захватом в без захвата (например, путем встраивания переменных), если это возможно.
Комментарии:
1. С самого начала переключение оптимизации на O2 говорит о другом.
2. @sweenish Sry Я не уверен, что вы имели в виду, говоря «рассказывает другую историю», не могли бы вы уточнить?
3. Вы уверены, что компилятор не может заметить, что вы выполняете несколько раз одно и то же вычисление в цикле и сохраняете только одну итерацию?
4. @MarcGlisse Компилятор не должен это оптимизировать. Именно так должна работать библиотека Google Bench library.
5. Библиотека не может изменить то, что говорит язык. Возможно, если бы вы сделали N volatile или вызвали DoNotOptimize(N) в цикле перед вызовом функции… Результат остается удивительным, но соотношение уменьшается.