Время для удаления указателей - PullRequest
5 голосов
/ 24 июня 2010

Hei community,

У меня небольшой вопрос, касающийся удаления указателей.

Я работаю с матрицами указатель-указатель размера Dimension 1024x1024.Поскольку я создаю их динамически, я удаляю выделенное для них пространство в конце программы.Но выполнение этого в обычном цикле стоит довольно много времени - я измерял около 2 секунд, используя тактовую частоту процессора.И 2 секунды это ОГРОМНО, когда программа запускается всего 15 секунд - плюс: функция, использующая эти выделенные указатели, вызывается более одного раза ...

Вот измеренный кусок кода, критичный ко времени, включая измерение:

time=clock();
for(i=0;i<xSize;i++){            //xSize is dynamic, but 1024 for the measurement
    delete [] inDaten[i];
    delete [] inDaten2[i];
    delete [] copy[i];
}
delete inDaten; delete inDaten2; delete copy;
time=clock()-time;
     time/=CLOCKS_PER_SEC;

Является ли удаление указателей ВСЕГДА таким долгим?Или я просто поступаю неправильно?

Я надеюсь, что кто-то здесь может мне помочь с этим.Так как я оптимизирую довольно сложную программу для более быстрой работы, я не могу использовать этот 2-секундный фрагмент кода.Это просто СЛИШКОМ медленно, по сравнению со всеми остальными частями.Но все же мне нужно иметь возможность реализовать этот код динамически.SmartPointers могут быть полезны, но если я правильно понимаю, им также нужно время, чтобы удалить себя - просто в другое время ...

Спасибо за ваши ответы!

Барадрист

РЕДАКТИРОВАТЬ: я только что узнал, что измерение этих delete-вычислений довольно медленно, потому что я не компилировал его в режиме выпуска.Так как отладчик вступает в игру, я измерил эти (в конце концов нереальные) числа, от которых у меня разболелась голова.Последняя программа оптимизируется достаточно автоматически, так что удаление больше почти не занимает времени.

В любом случае: спасибо за все полезные ответы!Они принесли мне много дополнительных знаний и вещей для размышления !!!!

Ответы [ 12 ]

3 голосов
/ 24 июня 2010

delete[] также будет вызывать деструкторы для каждого элемента массива, который добавляет время, если деструктор не тривиален.

Кроме этого - да, динамическое выделение памяти относительно дорого. Если вы не можете это терпеть - попробуйте выделить меньше блоков большего размера или обходитесь без динамического выделения в критичных ко времени вещах.

Умные указатели мало помогут - они сделают то же самое внутри. Они не для ускорения, а для удобства дизайна.

2 голосов
/ 24 июня 2010

Вот интересная тема " Узкое место выделения / выделения памяти? "

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

1 голос
/ 24 июня 2010

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

1 голос
/ 24 июня 2010

Не должно ли это быть:

delete [] inDaten; delete [] inDaten2; delete [] copy;

потому что при использовании они, очевидно, являются массивами. (По крайней мере, они выглядят слишком, вы не предоставили достаточно контекста).

1 голос
/ 24 июня 2010

Похоже, проблема в структуре ваших данных.Зачем вам нужно так много динамических распределений?Что можно сделать, чтобы уменьшить количество выделений?

Если освобождение указателей занимает 2 секунды, вероятно, для их выделения требуется как минимум столько же.

Освобождения их можно избежать, просто выйдяпрограмма рано.C ++ не дает никаких гарантий относительно того, что произойдет с выделенной памятью в то время, но ваша ОС, вероятно, так и поступает, поэтому в практических терминах это может быть простым способом сократить время выполнения на 2 секунды.1008 * Но это все еще оставляет> 2 секунды для распределения.

Лучше всего, я думаю, лучше попытаться структурировать данные.Можете ли вы показать нам, как матрица в настоящее время структурирована?

1 голос
/ 24 июня 2010

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

0 голосов
/ 25 июня 2010

Если все объекты, на которые ссылаются указатели в вашей матрице, относятся к одному и тому же типу (или, по крайней мере, к одному и тому же размеру), вы можете выделить один большой кусок памяти для их хранения и инициализации на месте.

0 голосов
/ 25 июня 2010

Если вы определили распределение / освобождение памяти как узкое место и хотите, чтобы это было быстрее, первое очевидное решение - использовать непрерывный буфер для ваших массивов.Вы по-прежнему можете предоставить матричный интерфейс, который обращается к ним как к двумерным массивам.

// Rudimentary Implementation
template <class T>
class SquareMatrix
{
public:
    explicit SquareMatrix(int i_size): 
        size(i_size), mat(new T[i_size * i_size]) {}

    ~SquareMatrix()
    {
        delete[] mat;
    }

    // could also be column depending on row-major/col-major
    T* operator[](unsigned int row)
    {
        return mat + row * size;
    }

    // could also be column depending on row-major/col-major
    const T* operator[](unsigned int row) const
    {
        return mat + row * size;
    }

private:
    unsigned int size;
    T* mat;
};

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

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

Я рекомендую вам по-прежнемузахватите профилировщик, а не полагайтесь на временные тесты и сделайте правильный анализ графа вызовов вашего кода.Это скажет вам точно, сколько времени тратится где.Может случиться так, что построение / уничтожение объектов в ваших матрицах не так дешево, как могло бы быть, например.

За исключением очевидной алгоритмической неэффективности, даже чрезвычайно знающие программисты часто ошибаются в отношении узких мест в своихкод.Профилировщик - ваш лучший друг, если важна эффективность.

0 голосов
/ 24 июня 2010

Оптимизация для этого состоит в том, чтобы распределять память в чанках, выделять отдельные указатели с размещением новых, а при удалении просто удалять весь чанк.

Вы должны быть осторожны, так как эта опция косвенно не вызывает деструктор для каждого объекта, выделенного для размещения new.

0 голосов
/ 24 июня 2010

Если объекты, на которые указывают ваши массивы, имеют нетривиальные деструкторы, вы мало что можете сделать, чтобы значительно улучшить время выполнения, не обращаясь к нему в первую очередь. В противном случае:

Вместо создания inDaten, inDaten2 and copy массивов размером isize из указателей на массивы isize почему бы не сделать их массивами размером isize*isize и вместо того, чтобы обращаться к отдельным элементам с помощью: array[i][j] обращаться к ним с array[i*isize+j]. Таким образом, вы можете очистить одним звонком delete [].

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