Подтвердить что ты не робот

Мне нужна высокая производительность. Будет ли разница, если я использую C или С++?

Мне нужно написать программу (проект для университета), которая решает (приближенно) проблему NP-hard. Это вариация задач линейного упорядочения. В общем, у меня будут очень большие входы (как Графы) и постараюсь найти лучшее решение (на основе функции, которая будет "оценивать" каждое решение)

Будет ли разница, если я напишу это в коде стиля C (один основной и функции) или создать класс Solver, создать экземпляр и вызвать метод "run" из основного (похожего на Java)

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

Спасибо!

4b9b3361

Ответ 1

Нет.

Наибольшие выигрыши/недостатки производительности будут выполняться на алгоритме, который вы реализуете, и сколько ненужной работы вы выполняете (ненужная работа может состоять из перерасчета предыдущего значения, которое могло быть кэшировано, для использования слишком большого количества malloc/free vs, используя пулы памяти, передавая большие неизменяемые данные по значению вместо ссылки)

Ответ 2

Самый дорогой блок для оптимального кода больше не является языком (для правильно скомпилированных языков), а скорее программистом.

Ответ 3

Нет, если вы не используете виртуальные функции.

Изменить: Если у вас есть случай, когда вам нужна динамическая динамика во время выполнения, то да, виртуальные функции выполняются так же быстро или быстрее, чем созданный вручную оператор if-else. Однако, если вы закроете ключевое слово virtual перед методом, но на самом деле вам не нужен полиморфизм, тогда вы будете платить лишние накладные расходы. Компилятор не будет оптимизировать его во время компиляции. Я просто указываю на это, потому что это одна из особенностей С++, которая ломает принцип "нулевой надбавки" (цитируя Stroustrup).

В качестве побочного примечания, поскольку вы упоминаете о тяжелом использовании математики fp:

Следующие gcc-флаги могут помочь вам ускорить процесс (я уверен, что для визуального С++ есть эквивалентные, но я не использую его): -mfpmath=sse, -ffast-math и -mrecip ( Последние два "немного опасны", что означает, что они могут дать вам странные результаты в кросс-кейсах в обмен на скорость. Первая из них немного снижает точность - у вас есть 64-битные удваивания вместо 80-битных - но эта дополнительная точность часто не нужна.) Эти флаги будут одинаково хорошо работать для компиляторов C и С++.

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

Ответ 4

Правило большого пальца - не оптимизируйте, пока не узнаете, что нужно оптимизировать. Итак, начните с С++ и у вас есть рабочий прототип. Затем профилируйте его и заново закрепите шейки бутылки в сборе. Но, как отмечали другие, выбранный алгоритм будет иметь гораздо больший эффект, чем язык.

Ответ 5

Говоря о производительности, все, что вы можете сделать в C, можно сделать на С++. Например, известно, что виртуальные методы являются "медленными", но если это действительно проблема, вы все равно можете прибегать к идиомам C.

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

Ответ 6

Класс Solver будет построен один раз, я беру его, и метод run выполняется один раз... в такой среде, вы не увидите разницы. Вместо этого здесь нужно следить за:

  • Управление памятью очень дорого. Если вам нужно сделать много маленьких malloc() s, операционная система съест ваш обед. Примите решительные меры для повторного использования любых структур данных, которые вы создаете, если вы знаете, что скоро будете делать то же самое!

  • Создание экземпляров классов обычно означает... выделение памяти! Опять же, практически нет затрат на создание экземпляра нескольких объектов и повторное использование их. Но будьте осторожны с созданием объектов, чтобы их просто разорвать и быстро их перестроить!

  • Выберите правильный вкус плавающей запятой для вашей архитектуры, насколько это позволяет проблема. Возможно, что double будет быстрее, чем float, хотя для этого потребуется больше памяти. Вы должны поэкспериментировать, чтобы точно настроить это. В идеале вы будете использовать #define или typedef, чтобы указать тип, чтобы вы могли легко его изменить в одном месте.

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

Ответ 7

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

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

Ответ 8

Пока вы не используете какие-либо виртуальные функции и т.д., вы не заметите существенных различий в производительности. Ранняя С++ была скомпилирована для C, поэтому, пока вы знаете точные точки, где это создает значительные накладные расходы (например, с виртуальными функциями), вы можете четко рассчитать разницу.

Кроме того, я хочу отметить, что использование С++ может дать вам много пользы, если вы используете библиотеки STL и Boost. Особенно STL обеспечивает очень эффективные и проверенные реализации наиболее важных структур данных и алгоритмов, поэтому вы можете сэкономить много времени разработки.

Эффективно это также зависит от используемого вами компилятора и того, как он будет оптимизировать код.

Ответ 9

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

Ответ 10

во-первых, запись на С++ не подразумевает использование ООП, посмотрите на алгоритмы STL. во-вторых, С++ может быть даже немного быстрее во время выполнения (время компиляции может быть ужасным по сравнению с C, но это потому, что современный С++ имеет тенденцию сильно полагаться на абстракции, которые налагают на компилятор).

edit: хорошо, см. Bjarne Stroustrup обсуждение qsort и std:: sort, а также статью, которая FAQ упоминает (Learning Standard С++ как новый язык), где он показывает, что код в стиле С++ может быть не только короче и читабельнее (потому что более высоких абстракций), но и несколько быстрее.

Ответ 11

Другой аспект:

Шаблоны С++ могут быть отличным инструментом для создания типов/ оптимизированные варианты кода.

Например, C qsort требует вызова функции для компаратора, тогда как std::sort может вставить переданный функтор. Это может существенно повлиять на то, что сравнивать и своп сами по себе дешевы.

Обратите внимание, что вы можете генерировать "настраиваемые qsorts", оптимизированные для разных типов с заграждением определений или генератором кода, или вручную - вы могли бы делать эти оптимизации на C тоже, но при гораздо более высокой стоимости.

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

Ответ 12

Хорошие ответы. Я бы сказал так:

  • Сделайте алгоритм максимально эффективным с точки зрения его формальной структуры.

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

  • Тем не менее, одноэтапный шаг на уровне разборки. Вы должны увидеть, что он очень непосредственно работает над вашей проблемой. Если он проводит много циклов, входящих и выходящих из подпрограмм, попробуйте некоторые подкладки (или макросы). Если он блуждает в распределение памяти и освобождение, большую часть времени останавливайтесь на этом. Если он получил внутренние петли, где накладные расходы цикла составляют большой процент, попробуйте развернуть цикл.

Как вы можете сделать это как можно быстрее.

Ответ 13

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

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

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

вы также можете автоматически создавать hotspot-код с помощью шаблонов и позволять компилятору оптимизировать его, если у вас есть такие вещи, как короткие петли разных размеров. Чтобы узнать производительность и перейти к своим узким местам, Intel vtune или oprofile чрезвычайно полезны.

надеюсь, что поможет

Ответ 14

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