Мне нужна высокая производительность. Будет ли разница, если я использую C или C ++? - PullRequest
18 голосов
/ 17 ноября 2009

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

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

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

Спасибо!

Ответы [ 14 ]

58 голосов
/ 17 ноября 2009

номер

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

19 голосов
/ 17 ноября 2009

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

9 голосов
/ 17 ноября 2009

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

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

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

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

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

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

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

6 голосов
/ 17 ноября 2009

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

3 голосов
/ 17 ноября 2009

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

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

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

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

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

1 голос
/ 17 ноября 2009

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

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

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

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

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

1 голос
/ 17 ноября 2009

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

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

1 голос
/ 17 ноября 2009

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

1 голос
/ 17 ноября 2009

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

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

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

...