Выделение памяти внутри цикла против внешнего цикла - PullRequest
3 голосов
/ 05 августа 2010

Есть ли заметное снижение производительности при выделении БОЛЬШИХ кусков памяти кучи в каждой итерации цикла?Конечно, я освобождаю его в конце каждой итерации.

Альтернативой может быть выделение один раз перед входом в цикл, повторное использование его на всех итерациях и, в конечном итоге, освобождение его после выхода из цикла.Смотрите код ниже.

// allocation inside loop
for(int i = 0; i < iter_count; i++) {
    float *array = new float[size]();
    do_something(array);
    delete []array;
}

// allocation outside loop
float *array = new float[size]();
for(int i = 0; i < iter_count; i++) {
    do_something(array);
}
delete []array;

Ответы [ 5 ]

3 голосов
/ 05 августа 2010

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

float *array = new float[size];
2 голосов
/ 05 августа 2010
  • Даже если распределение было постоянным, у вас вместо T значение TxN. Кроме того, если у вас есть какая-либо инициализация памяти чанка (даже если он просто устанавливается в ноль), вы постоянно перебиваете свой кэш.
  • Основным ударом по производительности при распределении кучи является фрагментация, а не время выделения, что является накопительной проблемой.Накапливайся меньше.

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

Итак, есть прямое попадание, которое можно измерить напрямую: сколько стоит new / delete по сравнению с do_something()?если do_something стоит дорого, вы не можете измерить много.

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

2 голосов
/ 05 августа 2010

Никогда на самом деле не знаешь, если не проверишь, насколько велик его удар, но если нет причин размещать его внутри цикла, не делай этого. Распределение большого количества памяти может быть медленным, и если вы сделаете это достаточно, это замедлит ваш код.
То же самое можно сказать о чем-либо внутри цикла. Если его там не нужно, он будет работать быстрее, если его убрать (насколько быстрее все зависит от того, что это такое, а выделение памяти требует большего, чем другие вещи), но если это делает код лучше / проще, это может быть Стоит оставить это в курсе.

0 голосов
/ 05 августа 2010

Перемещение операций из циклов улучшает производительность.Распределение вне будет быстрее, в частности, если iter_count большое.

Оператор new() потенциально (но не всегда!) Заставляет вызов операционной системы получить больше памяти, что дорого (условно говоря).Точно так же вызов delete() освобождает память, потенциально (но не всегда!) Вызывающую также вызов операционной системы.

Во всех случаях убедитесь, что do_something() не делает никаких предположений относительно содержимого памятион не инициализирован и может содержать случайные данные.

0 голосов
/ 05 августа 2010

Накладные расходы зависят от «веса» do_something (). Поскольку он действует на массив, я предполагаю, что это немного больше, чем несколько скалярных операций. Так что в этом случае вы не заметите никакого ускорения, переместив выделение / удаление за пределы цикла. Однако в показанном выше случае нет особых оснований этого не делать.

...