Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.07.2011, 10:43   #1
FiloXSee
Пользователь
 
Регистрация: 07.06.2011
Сообщений: 28
По умолчанию Методы оптимизации памяти

Написал статью по оптимизации памяти в программах на С++. Ее можно почитать тут:
http://itw66.ru/blog/c_plus_plus/491.html

А какие методы вы можете предложить по повышению эффективности программы, при помощи организации данных в памяти определенным образом?
Портал "It Works" (http://itw66.ru), на котором веду множество блогов по программированию и философии (FiloXSee).
FiloXSee вне форума Ответить с цитированием
Старый 05.07.2011, 10:57   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
В третьих есть риски утечек памяти.
это не зависит от частоты, можно выделить один раз память и умудрится из нее сделать утечку.
Цитата:
а значит если выделить память два раза для двух объектов, то они вряд ли будут лежать в соседней памяти. Поэтому работа с такими объектами будет медленнее.
и что с того что они лежат не рядом?
почему медленнее, то? где обьяснения причин?(если что я знаю почему)
Цитата:
Пробегаться по такой коллекции будет значительно эффективнее, если все объекты будут последовательно в памяти.
непрерывность требование массива, а если список, то там особо разницы нет(кроме жирного пункта)
Цитата:
Но эта проверка занимает 23-24 (указаны для процессора Cell, PS3) цикла процессора
простая проверка флага занимает 24 такта?
не знал что банальный test dword[ecx+<смещение>],0
будет так долго выполнятся...
Цитата:
При проходе по такой коллекции для получения каждого нового элемента будет обращение к памяти.
изучите STL чтоли, он выделяет памяти больше чем надо, в итоге отнюдь не каждый раз идет обращение к памяти.(свойство вместимость то не зря есть там)
Цитата:
Одна только эта реорганизация
ну да, теперь надо вечно разименовывать указатели(на что тоже тратятся такты)
и дальше, данные то теперь не рядом хранятся, тут вступает пункт выделенный жирным.
да и возможность утечек выше.
Цитата:
Работайте не с объектами а с коллекциями объектов
если у нас итак коллекция, то не стоит, убирать объект её состовляющий, так как нарушается группировка данных(жирный пункт)
да и работать с таким не очень уютно
Цитата:
Поблочное выделение памяти
вот тут согласен(кроме использования пункта три)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 05.07.2011 в 11:05.
Пепел Феникса вне форума Ответить с цитированием
Старый 05.07.2011, 11:09   #3
FiloXSee
Пользователь
 
Регистрация: 07.06.2011
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
непрерывность требование массива, а если список, то там особо разницы нет(кроме пункта выше в котором нет причин)
Массивы объектов - это чаще всего массивы указатели на классы. Поэтому они не будут в памяти последовательно. Поэтому и есть этот пункт, призывающий убедиться в последовательности объектов в памяти, для эффективности работы.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
простая проверка флага занимает 24 такта?
Проверка флага - это не долго. Долго перестраивать конвейер процессора, в случае ошибки бранч предикшена (который на PS3 и так слабый).

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
изучите STL чтоли, он выделяет памяти больше чем надо, в итоге отнюдь не каждый раз идет обращение к памяти.(свойство вместимость то не зря есть там)
Я же написал "для получения объекта", а не для его создания. Т.е. идем по массиву указателей на объекты. Чтобы проверить поле каждого объекта нужно разыменовать указатель и получить объект из памяти. Кашмис будет стопроцентный, т.к. объекты идут не подряд в памяти. Это значит, что для получения каждого объекта будет обращение к оперативной памяти, а это уже 600 тактов процессора. И так для каждого объекта.
Портал "It Works" (http://itw66.ru), на котором веду множество блогов по программированию и философии (FiloXSee).
FiloXSee вне форума Ответить с цитированием
Старый 05.07.2011, 11:15   #4
FiloXSee
Пользователь
 
Регистрация: 07.06.2011
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
ну да, теперь надо вечно разименовывать указатели
Разыменование указателя - это получение данных из памяти по указателю:
Обращение к L1 - 20 тактов.
Обращение к L2 - 100 тактов.
Обращение к общей памяти - 600 тактов.
Это значит, что разыменовывать указатель очень дешево, если все данные в памяти процессора и намного выгоднее чем кэшмис.

Если вы работаете с данными которые уже в памяти, то кэшмиса не будет. А если заменить указатель на сами данные, то размер увеличивается, данные не помещаются в кэш и все работает намного дольше т.к. для каждого объекта нужно заново получить данные из оперативной памяти.
Портал "It Works" (http://itw66.ru), на котором веду множество блогов по программированию и философии (FiloXSee).
FiloXSee вне форума Ответить с цитированием
Старый 05.07.2011, 11:17   #5
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Массивы объектов - это чаще всего массивы указатели на классы.
массивы объектов, и массивы указателей на объекты это разное, массив объектов это массив объектов.
std::vector<class> и std::vector<class*> совсем разные вещи, но говорите вы про первое
Цитата:
Долго перестраивать конвейер процессора, в случае ошибки бранч предикшена (который на PS3 и так слабый).
тут пожалуй да, но есть одно НО, тут надо смотреть на длительность той самой процедуры восстановления объекта, ибо если она долгая и редко нужна, то лучше проверять всетаки.
Цитата:
Т.е. идем по массиву указателей на объекты.
тогда и говорите что речь об массивах указателей.
а то у вас написано коллекция объектов, ну я на код внимания не обратил.(в коде то коллекция указателей на объекты)
Цитата:
Если вы работаете с данными которые уже в памяти, то кэшмиса не будет. А если заменить указатель на сами данные, то размер увеличивается, данные не помещаются в кэш и все работает намного дольше т.к. для каждого объекта нужно заново получить данные из оперативной памяти.
один хрен нам работать с данными по указателю, так что на данный момент не вижу смысла(итог тот же кэшмис)
да и не думаю что проц будет ради работы с полем класса, грузить в кэш весь объект
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 05.07.2011 в 11:20.
Пепел Феникса вне форума Ответить с цитированием
Старый 05.07.2011, 11:19   #6
FiloXSee
Пользователь
 
Регистрация: 07.06.2011
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
да и работать с таким не очень уютно)
Внешний код работает с коллекцией, так что ему без разницы как она устроена. Хранить однотипные данные в своих массивах намного эффективнее чем группировать их в объекты и хранить объекты.

ООП - это хорошо для бизнесс логики. Но часто очень плохо, когда речь идет о данных и работе с ними. Если нужно часто перемножать матрицы, то значительно эффективнее, если они будут в смежной памяти, чем в составе своих объектов.
Портал "It Works" (http://itw66.ru), на котором веду множество блогов по программированию и философии (FiloXSee).
FiloXSee вне форума Ответить с цитированием
Старый 05.07.2011, 11:23   #7
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Но часто очень плохо, когда речь идет о данных и работе с ними. Если нужно часто перемножать матрицы, то значительно эффективнее, если они будут в смежной памяти, чем в составе своих объектов.
зависит от приложения.
тут нужно верно проектировать, если нам чаще нужен весь объект а не отдельное поле, то лучше группировать данные, если же чаще нужно какое то отдельное поле, то лучше будет если оно будет отдельно.(причем это все для коллекций, для одиночных объектов не особо актуально)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 05.07.2011, 11:32   #8
FiloXSee
Пользователь
 
Регистрация: 07.06.2011
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
тут нужно верно проектировать, если нам чаще нужен весь объект а не отдельное поле, то лучше группировать данные, если же чаще нужно какое то отдельное поле, то лучше будет если оно будет отдельно.
Согласен. Это все более справедливо для систем с большим количество данных чем для иерархий логических объектов. Хотя и для них пункт 3 является актуальным.
Портал "It Works" (http://itw66.ru), на котором веду множество блогов по программированию и философии (FiloXSee).
FiloXSee вне форума Ответить с цитированием
Старый 05.07.2011, 11:38   #9
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

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

Конечно, в общеоразовательных целях можно попробовать разное и посмотреть как оно влияет на производительность.
Вот например Intel для достижения максимальной производительности рекоммендует выранивать блоки памяти как минимумум по 64 байтной границе, еще лучше если и размер самих блоков кратен 64. Последовательное заполнение это конечно позитив, но принимая во внимание, что современные процы могут кешить данные из 8 различных страниц памяти одновременно то позитив от подобного раположения будут испытывать только однопроходные процедуры не использующие одни и те же данные многократно. Плюс общая рекоменданция это не столько последовальное расположение данных сколько регулярное (разрешен ненулевой интервал, не больше 64 байт, между группами данных). Плюс есть операции перещения данных в обход кеша, которые в теории страшно увеличивают производительность. Ну, вобщем есть много различных путей, и не факт, что компилятор делает хуже.
f.hump вне форума Ответить с цитированием
Старый 05.07.2011, 11:50   #10
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Цитата:
Обращение к L1 - 20 тактов.
Обращение к L2 - 100 тактов.
Обращение к общей памяти - 600 тактов.
Ни хрена себе, сказал я себе.
Такое возможно если память используется несколькими потоками одновременно и любая операция на ней приводит к событию синхронизации. Если память приватная, то эти цифры нужно поделить на 5, чтобы приблизиться к реальности.

Кстати, случайно заметил постоянные референсы на PS3, это что про оптимизацию для PS3?
Потому что я писал про х86 от Intel.

Последний раз редактировалось f.hump; 05.07.2011 в 11:55.
f.hump вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Методы оптимизации кода FiloXSee Общие вопросы C/C++ 33 09.06.2011 09:06
Методы оптимизации Lazio Фриланс 3 11.12.2010 12:05
методы оптимизации первого порядка Olenka555 Помощь студентам 0 21.05.2010 16:43
Методы оптимизации в Excel Raikhman Microsoft Office Excel 2 10.02.2009 11:17