C против С++ для производительности в распределении памяти

Я планирую участвовать в разработке кода, написанного на языке C для анализа сложных проблем в Монте-Карло. Эти коды выделяют огромные массивы данных в памяти для ускорения его производительности, поэтому автор кода выбрал C вместо С++, утверждая, что с помощью C.

можно сделать более быстрый и надежный (относительно утечки памяти) код.

Вы согласны с этим? Каким будет ваш выбор, если вам нужно хранить в памяти 4-16 ГБ массивов данных?

Ответ 1

Определенно С++. По умолчанию нет существенной разницы между этими двумя, но С++ предоставляет пару вещей C:

  • Конструкторы/деструкторов. Это позволяет автоматизировать большинство операций управления памятью, повышая надежность.
  • распределяющие ресурсы для каждого класса. Они позволяют оптимизировать распределение, основанное на том, как конкретные объекты разрабатываются и/или используются. Это может быть особенно полезно, если вам нужно большое количество небольших объектов (чтобы дать один очевидный пример).

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

Ответ 2

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

Если автор кода может продемонстрировать разницу в производительности между кодом C и С++, выделяющим массив 4-16 ГБ, тогда (а) я удивлен, но в порядке, есть разница и (б) сколько раз программа собирается выделить такие большие массивы? Ваша программа на самом деле собирается потратить значительное количество времени на выделение памяти или большую часть времени занимает доступ к памяти и делает вычисления? Потребуется много времени, чтобы на самом деле сделать что-либо с массивом 4 ГБ, по сравнению с тем временем, которое требуется для распределения, а это значит, что вам следует беспокоиться о производительности "ничего", а не о производительности распределения. Спринтеры много заботятся о том, как быстро они выходят из блоков. Марафонские бегуны, не так много.

Вам также нужно быть осторожным, как вы ориентируетесь. Вы должны сравнивать, например, malloc(size) с new char[size]. Если вы протестируете malloc(size) против new char[size](), тогда это несправедливое сравнение, поскольку последнее устанавливает память в 0, а первое - нет. Сравните вместо calloc вместо этого, но также обратите внимание, что malloc и calloc оба доступны из С++ в (маловероятном) событии, что они действительно значительно быстрее.

В конечном счете, однако, если автор "владеет" или начал проект и предпочитает писать на C, а не на С++, тогда он не должен оправдывать это решение с вероятными ложными утверждениями о производительности, он должен его обосновать, сказав: Я предпочитаю C, и это то, что я использую ". Обычно, когда кто-то делает подобное выражение об эффективности языка, и, оказывается, тестирование не является истинным, вы обнаружите, что производительность не является реальной причиной предпочтения языка. Доказательство иска false не приведет к тому, что автор этого проекта вдруг начнет симпатизировать С++.

Ответ 3

Нет никакой реальной разницы между C и С++ с точки зрения распределения памяти. С++ Имеет больше "скрытых" данных, таких как виртуальные указатели и т.д., Если вы выбрали виртуальные методы для своих объектов. Но выделение массива символов столь же дорого стоит на C, как и на С++, на самом деле они, вероятно, оба используют malloc для этого. С точки зрения производительности, С++ вызывает конструктор для каждого объекта в массиве. Обратите внимание, что это делается только в том случае, если он есть, конструктор по умолчанию ничего не делает и оптимизирован.

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

Ответ 4

Единственное, что в немилости С++ - это дополнительная сложность - объединить это с программистом, который использует его неправильно, и вы можете легко замедлиться. Использование компилятора С++ без возможностей С++ даст вам такую ​​же производительность. Используя С++ правильно, у вас есть несколько posisbilities, чтобы быть быстрее.

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

Основной смертельной ошибкой, которую вы могли бы сделать при распределении (на любом языке), является выделение 16 ГБ памяти, инициализация которой равна нулю, только для заполнения ее фактическими значениями позже.

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

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

Ответ 5

Для распределения необработанных данных в большинстве систем не должно быть разницы между C и С++, поскольку они обычно используют одни и те же механизмы библиотеки времени выполнения. Интересно, была ли это классическая ошибка, где они также измеряли время выполнения вызовов конструктора на С++ и удобно забывали о включении времени выполнения любого типа кода инициализации в C.

Кроме того, аргумент "более надежный (относительно утечки памяти)" не содержит воды, если вы используете RAII на С++ (как и должно быть). Если кто-то не ссылается на то, что утечка будет более надежно, использование RAII, интеллектуальных указателей и классов контейнеров уменьшит вероятность утечек, а не увеличит его.

Мои основные проблемы с распределением того, что большая память будет двоякой:

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

Ответ 6

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

Ответ 7

Вы также можете использовать семейство C функций распределения памяти в С++: как стандартные malloc, так и free, realloc для увеличения /shring массивов и alloca для выделения памяти в стеке.

Если вы перейдете с new, он будет выделять больше памяти, чем необходимо (главным образом, во время отладки), и выполнять дополнительные проверки на согласованность. Он также вызовет конструктор для классов. В выпуске release (-O3) различие будет незначительным для большинства приложений.

Теперь, что new приносит, что malloc не является на месте new. Вы можете предварительно распределить буфер, а затем использовать встроенный new, чтобы поместить свою структуру в этот буфер, тем самым мгновенно "распределяя" его.

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

Ответ 8

Если вам нужно хранить 4-16 ГБ массивов данных в памяти во время вычисления, и ваш компьютер имеет только 2 ГБ физической памяти, то что?

Что делать, если ваш компьютер имеет 16 ГБ физической памяти? Операционная система не занимает физической памяти?

Поддерживает ли операционная система даже адресное пространство 4 ГБ, 16 ГБ и т.д.

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