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

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

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

11
задан Andrei 25 March 2010 в 07:56
поделиться

8 ответов

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

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

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

23
ответ дан 3 December 2019 в 01:29
поделиться

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

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

Мои основные опасения по поводу выделения такого объема памяти были бы двоякими:

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

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

Язык - не ваша проблема , распределение и обход больших массивов - это.

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

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

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

3
ответ дан 3 December 2019 в 01:29
поделиться

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

1
ответ дан 3 December 2019 в 01:29
поделиться

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

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

Теперь то, что new приносит, а malloc - нет, это in-place new . Вы можете предварительно выделить буфер, а затем использовать in-place new , чтобы поместить свою структуру в этот буфер, тем самым сделав «выделение» его мгновенным.

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

0
ответ дан 3 December 2019 в 01:29
поделиться

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

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

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

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

0
ответ дан 3 December 2019 в 01:29
поделиться

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

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

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

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

8
ответ дан 3 December 2019 в 01:29
поделиться

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

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

3
ответ дан 3 December 2019 в 01:29
поделиться