Управление памятью в программировании становится неактуальной проблемой?
Управление памятью (или контроль) на самом деле является основной причиной, по которой я использую C и C ++.
Память сейчас сравнительно дешевая.
Не быстрая память. Мы по-прежнему рассматриваем небольшое количество регистров, например, кеш данных объемом 32 КБ для L1 на i7, 256 КБ для L2 и 2 МБ для L3 / ядро. Это говорит:
Если мы не говорим с точки зрения целевых платформ со строгими ограничениями на рабочую память (т.е. встроенные системы и т. П.), Должно ли использование памяти быть проблемой при выборе языка общего назначения сегодня?
Использование памяти на общем уровне, возможно нет. Я немного непрактичен тем, что мне не нравится идея блокнота, который занимает, скажем, 50 мегабайт DRAM и сотни мегабайт пространства на жестком диске, хотя у меня есть для этого больше и больше. Я был здесь в течение долгого времени, и мне просто странно и немного странно видеть, как такое простое приложение занимает относительно много памяти для того, что должно быть выполнимо с килобайтами. Тем не менее, я мог бы жить с самим собой, если бы столкнулся с такой вещью, если бы она все еще была милой и отзывчивой.
Причина, по которой управление памятью важно для меня в моей области, заключается не в том, чтобы вообще уменьшить использование памяти. Использование сотен мегабайт памяти не обязательно замедлит работу приложения каким-либо нетривиальным способом, если к этой памяти часто не обращаются (например, только при нажатии кнопки или какой-либо другой форме пользовательского ввода, что крайне редко, если вы речь идет о корейских игроках Starcraft, которые могут нажимать кнопку миллион раз в секунду).
Причина, по которой это важно в моей области, заключается в том, чтобы получить тесную и тесную память , к которой очень часто обращаются (например, зацикливаться на каждом кадре) на этих критических путях. Мы не хотим пропустить кэш каждый раз, когда получаем доступ к одному из миллиона элементов, к которым нужно обращаться в цикле каждый отдельный кадр. Когда мы перемещаем память вниз по иерархии от медленной памяти к быстрой памяти большими кусками, скажем, 64-байтовыми строками кэша, очень полезно, если все эти 64 байта содержат релевантные данные, если мы можем поместить данные из нескольких элементов в эти 64 байта, и если наши шаблоны доступа таковы, что мы используем все это до того, как данные будут выселены.
Эти часто используемые данные для миллиона элементов могут занимать всего 20 мегабайт, даже если у нас есть гигабайты. Это по-прежнему сильно отличает частоту кадров, циклически повторяющую эти данные в каждом нарисованном кадре, если память тесно и близко друг к другу, чтобы минимизировать пропуски кэша, и именно здесь управление / контроль памяти так полезно. Простой визуальный пример сферы с несколькими миллионами вершин:
Вышеупомянутое на самом деле медленнее, чем моя изменяемая версия, поскольку она тестирует постоянное представление структуры данных меша, но, за исключением этого, я привык бороться за достижение такой частоты кадров даже на половине этих данных (по общему признанию, аппаратное обеспечение стало быстрее, так как моя борьба ) потому что я не научился минимизировать потери в кеше и использовать память для данных меша. Сетки являются одними из самых хитрых структур данных, с которыми я сталкивался в этом отношении, потому что они хранят столько взаимозависимых данных, которые должны синхронизироваться, таких как многоугольники, ребра, вершины, столько карт текстур, сколько пользователь хочет присоединить, веса костей, карты цветов, наборы выбора, объекты морфинга, веса ребер, материалы полигонов и т. д. и т. д. и т. д.
За последние пару десятилетий я разработал и внедрил несколько ячеистых систем, и их скорость часто была очень пропорциональна их использованию памяти. Несмотря на то, что я работаю с этим, гораздо больше памяти, чем когда я начинал, мои новые сетчатые системы более чем в 10 раз быстрее, чем мой первый проект (почти 20 лет назад), и в значительной степени потому, что они используют около 1/10 память. В новейшей версии даже используется индексированное сжатие для сжатия как можно большего количества данных, и, несмотря на накладные расходы по обработке при декомпрессии, сжатие фактически улучшило производительность, потому что, опять же, у нас так мало драгоценной быстрой памяти. Теперь я могу уместить сетку из миллиона полигонов с координатами текстуры, сгибом кромок, назначениями материалов и т. Д. Вместе с пространственным индексом для него примерно в 30 мегабайт.
Вот изменчивый прототип с более чем 8 миллионами четырехугольников и многоуровневой схемой подразделения на i3 с GF 8400 (это было несколько лет назад). Это быстрее, чем моя неизменяемая версия, но не используется в производстве, так как я обнаружил, что неизменяемая версия намного проще в обслуживании, и снижение производительности не так уж плохо. Обратите внимание, что в каркасном изображении указаны не фасеты, а заплатки (в действительности, это кривые, иначе вся сетка будет сплошной черной), хотя кисть изменяет все точки фасета.
Так или иначе, я просто хотел показать кое-что из вышеперечисленного, чтобы показать некоторые конкретные примеры и области, в которых управление памятью очень полезно, а также, надеюсь, чтобы люди не думали, что я просто говорю из моей задницы. Я склонен немного раздражаться, когда люди говорят, что память настолько обильна и дешева, потому что речь идет о медленной памяти, такой как DRAM и жесткие диски. Это все еще так мало и так ценно, когда мы говорим о быстрой памяти, а производительность для действительно критических (то есть, общего случая, а не для всех) путей связана с воспроизведением этого небольшого объема быстрой памяти и его использованием настолько эффективно, насколько мы можем ,
Для такого рода вещей действительно полезно работать с языком, который позволяет проектировать высокоуровневые объекты, такие как, например, C ++, и при этом сохранять эти объекты в одном или нескольких смежных массивах с гарантией того, что память все такие объекты будут представлены непрерывно и без каких-либо ненужных накладных расходов памяти на объект (например: не все объекты нуждаются в отражении или виртуальной диспетчеризации). Когда вы на самом деле переходите в эти критические для производительности области, это становится повышением производительности, когда такой контроль над памятью, например, работает с пулами объектов и использует примитивные типы данных, чтобы избежать накладных расходов на объекты, затрат на сборку мусора и обеспечить постоянный доступ к памяти. вместе смежные.
Поэтому управление / контроль памяти (или ее отсутствие) на самом деле является доминирующей причиной в моем случае выбора того, какой язык наиболее продуктивно позволяет мне решать проблемы. Я действительно пишу свою долю кода, которая не критична для производительности, и для этого я склонен использовать Lua, который довольно легко внедрить из C.