Почему мой код C работает медленно?

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

Я использую операторы присваивания, условные (вложенные), циклы, вызовы функций и обратные вызовы.

Каковы хорошие ссылки на общие проблемы производительности C?

Есть ли хороший профилировщик, который я могу использовать?


Спасибо вам всем

Спасибо за все ваши материалы. Вы абсолютно правы: это алгоритмы, которые могут замедлять работу (резко). Хотя некоторые улучшения производительности могут быть достигнуты благодаря практике кодирования – я на 100% убежден, что только ошибочный алгоритм может резко замедлить работу .

На самом деле: я работал над деревьями RB и вставлял узлы в порядке возрастания. Это заняло огромное время (так же плохо, как Дерево двоичного поиска (Skewed)). После поиска вашего совета я проверил алгоритм, где я ошибся в балансировке, из-за которой дерево наклонялось (перекошено). Я исправил это.

Еще раз спасибо за предложения.

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

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

Другие люди рекомендовали gprof – во-вторых, если вы заинтересованы в профилировании своего кода. Я также использовал VTune раньше, и мне понравилось. Но сначала убедитесь, что вы понимаете свой код и что он делает, и что алгоритм, который вы реализуете, эффективен по времени, когда вы имеете дело с размером данных, которые вы ожидаете от него.

В стороне, использование C не означает, что ваш код будет автоматически работать быстрее. Как правило, связанный код ввода-вывода не улучшает производительность. Тяжелый код пользовательского интерфейса может не использовать язык низкого уровня. Как правило, C – лучший язык реализации, где вам нужен доступ на низком уровне, при взаимодействии с аппаратными или низкоуровневыми службами операционной системы, или если у вас есть очень специфические и строгие требования к производительности, которые сложно встретить на высоком уровне, сбор данных с мусором , Или, если вам нравится C, но это, очевидно, субъективный вопрос.

Это измученный предмет.

Профилирование – один из вариантов, но есть пара старомодных методов, которые работают на удивление хорошо, если у вас есть отладчик:

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

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

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

объяснил на WikiHow

хорошее объяснение SO

не теряйте время, пытаясь найти «дорогие» операции. в C почти нет, кроме библиотек, конечно.

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

в обозначении «большой O»: полное сопоставление O(nxm) равно O(nxm) или примерно O(n^2) если n и m аналогичны. но последовательное считывание в среднем равно O(n/2) , поэтому при чтении плюс O(n^2) при сравнении. с хешированием это будет aO(2n)+bO(2n)+cO(n^2) или просто O(n^2)

оптимизировать алгоритмы, а не код.

Проверьте выделение памяти. И вызовы функций. Если вы используете gcc, используйте параметр -pg, чтобы скомпилировать его с информацией профилирования и запустить ее через gprof . VS Team System Edition поставляется с собственным профилировщиком. Итак, возьмите свой выбор.

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

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

Для получения информации о MSVC см. Этот пост или эту запись в блоге о профилировании под MSVS или даже этот вопрос, и в частности ответ AMD CodeAnalyst

У вас есть доступ к инструментальной цепочке GNU? Если да, проверьте «gprof». Это профайлер … хорошо для поиска узких мест.