C: выполнение заданий, бинарные операции и так далее - PullRequest
5 голосов
/ 23 мая 2010

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

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

Ответы [ 6 ]

10 голосов
/ 23 мая 2010

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

Как правило, при настройке производительности следует уделять больше внимания алгоритмам, за которыми следуют локальность памяти и оптимизация кэша. Лучшими инструментами, которые у вас будут, являются профилировщики (oprofile, valgrind, cachegrind и т. Д.), За которыми следует понимание архитектуры машины (неоптимальные комбинации команд, ограничения выравнивания, иерархия и размер памяти) и язык ассемблера для вашего ЦП (чтобы поймать меньше, чем проблемы оптимального внутреннего цикла).

Если вас интересует микрооптимизация в архитектуре Intel (и всех процессорах, совместимых с Intel), этот является обязательным для чтения (PDF). На сайте Агнера есть более интересные руководства.

9 голосов
/ 23 мая 2010

Мне кажется, что вы очень смущены всем этим. Давайте рассмотрим некоторые из этих мифов, которые вы вытащили.

Кастинг медленный по сравнению с обычными заданиями.

Это действительно зависит от того, что вы кастуете. Между разными типами адресов нет; там на самом деле free , так как вы просто применяете другую интерпретацию к одному и тому же значению. Приведение между различными значениями числового типа может быть немного медленнее (а иногда выполняется неявно при назначении), но все еще очень быстро.

Медленные вызовы функций.

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

Двоичные операции выполняются быстрее, чем обычные операции.

Что такое «нормальная работа»? FWIW, сложение является бинарной операцией. Как и умножение. На современном оборудовании они оба довольно быстрые. Позвольте компилятору беспокоиться об этом. Гораздо важнее сосредоточиться на описании того, что вы делаете правильно.

Теперь, для вещей, которые действительно стоят :

  • I / O.
  • Распределение памяти.
  • Память копий.
  • Глубоко вложенные (или очень длинные) циклы.

Не спускайте с них глаз; там, где программное обеспечение обычно работает медленно. И всегда выбирайте хорошие алгоритмы и структуры данных.

2 голосов
/ 23 мая 2010

Когда-то была книга под названием Эффективный C . Несколько позже появилась книга под названием Эффективное программирование на C / C ++: меньше, быстрее, лучше . Еще совсем недавно был назван Efficient C ++ .

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

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

1 голос
/ 23 мая 2010

Я много слышал о производительности в C ...

Кто-то дал вам очень странных идей. Мне особенно нравится различие между "бинарными" и "обычными" операциями. Я думал, что для компьютера двоичный файл был нормальным. Кто-то должен будет объяснить мне это различие.

Я хотел бы увидеть диаграмму, чтобы получить общее представление о том, что мне следует делать и чего следует избегать при написании высокопроизводительных программ.

Я предоставлю вам таблицу ниже. Предполагается, что вы узнали о языке Си на уровне Керниган и Ричи, который является классическим учебником по Си и единственной книгой по Си, которая вам когда-либо понадобится (хотя другие полезны).

    Have you read Jon Bentley's book "Programming Pearls"?  --no--> read it
             |
             | yes
             V
    Have you read Peter van der Linden's book 
    "Expert C Programming: Deep C Secrets"?                 --no--> read it
             |
             | yes
             V
    Have you learned how to use valgrind --tool=callgrind
    and the kcachegrind visualizer?                         --no--> learn them
             |
             | yes
             V
    Congratulations!  You are now equipped to write 
    reasonably efficient C programs.

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

1 голос
/ 23 мая 2010

Где вы слышите эти вещи ?? Из всех мифов, которые «распространяются» в этой области, это, пожалуй, самый удивительный из тех, что я слышал.

C максимально приближен к машинному языку и при этом остается машинно-независимым языком высокого уровня.

Все остальные ответы верны.

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

1 голос
/ 23 мая 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...