Время работы программы, основанной па массивах, росло квадратично
Время работы программы, основанной па массивах, росло квадратично с ростом т, как я и предполагал, и постоянный множитель в этой зависимости имел достаточно разумное значение. Однако для первой реализации со списком время выполнения уже для m = 10 ООО оказывалось на порядок больше, чем для массивов, и росло быстрее, чем 0(т2). Что-то в моих рассуждениях было неверным.
Вначале мне показалось, что проблема в рекурсии. Помимо дополнительных затрат па рекурсивный вызов функции, глубина рекурсии функции rinsert определяется положением искомого элемента, то есть может быть записана как О(п). После рекурсивного перебора элементов к концу списка значение передастся обратно последовательным присваиванием его указателям. Когда я заменил рекурсивную функцию па итеративную, описанную в решении задачи 4, время выполнения сократилось примерно в три раза.
Затем я решил изменить метод выделения памяти па метод, описанный в задаче 5. Вместо того чтобы выделять память при каждой операции вставки, конструктор выделял ее целым блоком под m узлов, а функция insert использовала эту память но мере необходимости. Улучшение было вызвано двумя причинами.
1. Модель затрат времени выполнения из приложения 3 показывает, что выделение памяти потребляет па два порядка больше времени, чем большинство простых операций. Мы заменили m таких дорогостоящих операций одной.
2. Модель затрат памяти из того же приложения говорит нам, что, если узлы выделяются блоком, на каждый из них уходит по 8 байт (4 байта па целое и
4 па указатель); 40 ООО узлов занимают 320 Кбайт памяти и отлично помещаются в кэше второго уровня моего компьютера. Если узлы выделять по отдельности, па каждый из них будет тратиться 48 байт памяти и полный объем в 1,92 Мбайт превысит объем кэша второго уровня.
В другой системе с более эффективной подпрограммой выделения памяти удаление рекурсии ускорило работу в пять раз, тогда как переход к выделению памяти блоком дал всего лишь 10% выигрыш по скорости. Кэширование и удаление рекурсии, как и большинство других методов оптимизации, иногда дают значительные результаты, а иногда практически никаких.
Алгоритм вставки элемента в массив ищет подходящее место для вставляемого элемента, а затем сдвигает все последующие, освобождая для него место. Ал го- ритм вставки элемента в список делает только первую часть работы, но не вторую: сдвигать элементы больше нет необходимости. Почему же на вдвое меньшую работу программа, использующая списки, затрачивает вдвое больше времени? Во- первых, эта программа использует вдвое больше памяти: для больших списков приходится считывать 8 байт и помещать их в кэш, тогда как реально используются только 4 байта. Во-вторых, в массивах обращение к элементам хорошо предсказуемо, тогда как при работе со списками ячейки памяти считываются в случайном порядке.
Опубликовал vovan666
April 17 2013 00:03:26 ·
0 Комментариев ·
3852 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.