Почему мой код на C работает медленно? - PullRequest
2 голосов
/ 19 февраля 2009

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

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

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

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


Спасибо всем

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

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

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

Ответы [ 6 ]

20 голосов
/ 19 февраля 2009

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

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

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

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

3 голосов
/ 20 февраля 2009

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

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

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

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

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

объяснено на WikiHow

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

2 голосов
/ 19 февраля 2009

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

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

в нотации 'big O': сравнение полного набора составляет O(n x m) или примерно O(n^2), если n и m похожи. но последовательное чтение в среднем равно O(n/2), поэтому при чтении все равно O(n^3/2) плюс при сравнении O(n^2). с хешированием это будет aO(2n)+bO(2n)+cO(n^2), или просто O(n^2)

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

1 голос
/ 19 февраля 2009

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

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

Информацию о MSVC см. В этом сообщении или в этой записи блога о профилировании в MSVS или даже в этом вопросе, в частности в ответе CodeAnalyst AMD

1 голос
/ 19 февраля 2009

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

0 голосов
/ 19 февраля 2009

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

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