Сравнение производительности (нормальный вызов функции против for_each + mem_fun против лямбда-выражения) в C ++ - PullRequest
1 голос
/ 06 декабря 2010

Что является лучшим (по производительности) среди этих фрагментов?

1)

for(list<Enemy*>::iterator iter = enemies.begin(); iter != enemies.end(); iter ++)
   (*iter)->prepare(time_elapsed);

2)

for_each(enemies.begin(), enemies.end(), [time_elapsed] (Enemy *e) {e->prepare(time_elapsed);});

3)

for_each(enemies.begin(), enemies.end(), bind2nd(mem_fun1<void, Enemy, GLfloat>(&Enemy::prepare), time_elapsed));

Ответы [ 4 ]

1 голос
/ 06 декабря 2010

Лямбды - самое быстрое решение. Существуют специальные оптимизации, связанные с получением ссылок на переменные на основе стека. Кроме того, в C ++ 0x они FAR более гибкие, чем любые другие вещи, связанные с привязкой, и первый цикл также имеет недостаток ясности. Лямбды - это победители во всех отношениях.

Тем не менее, я серьезно думаю о микрооптимизации, если только это не действительно внутренний цикл, который выполняется миллиарды раз.

0 голосов
/ 06 декабря 2010

Я сделал измерения без оптимизации компилятора:

2) и 3) имеют практически одинаковое время работы, вместо 1) в 10 раз медленнее. Я добавил также 4)

for each (Enemy* e in enemies)
      e->prepare(time_elapsed);

действительно для Visual C ++ 2010 и должно совпадать с Ferruccio:

for (var iter : enemies) { iter->prepare(time_elapsed); }

4) также почти так же быстро, как 2) и 3).

С -O2 у всех почти одинаковое время работы.

0 голосов
/ 06 декабря 2010

Ответ таков: «Это совсем не важно, пока вы не измерили , что что-то в данный момент недостаточно быстро ". Этот вопрос по сути преждевременной оптимизации. Пока он не будет слишком медленным , а вы не измерили цикл как узкое место, ваш приоритет - использовать код, который сообщает о том, что вы пытаетесь сделать в самом ясном способ . Сначала напишите хороший код, потом оптимизируйте.

0 голосов
/ 06 декабря 2010

2 и 3 по существу идентичны. 1 может быть быстрее, потому что он выполняет один вызов функции за итерацию, тогда как 2 и 3 выполняют два вызова функции за итерацию. С другой стороны, некоторые вызовы функций могут быть встроены. Единственный способ действительно сказать, это измерить.

Кроме того, поскольку вы добавляете лямбда-функции (C ++ 0x), почему бы не добавить в ваши измерения циклы на основе диапазона:

for (var iter : enemies) { iter->prepare(time_lapsed); }

конечно, если ваш компилятор их поддерживает.

РЕДАКТИРОВАТЬ: я только что заметил тег vc ++ 2010. К сожалению, ваш компилятор пока не поддерживает их: - (

...