Константы C, определенные во время соединения - PullRequest
4 голосов
/ 18 марта 2012

У меня ОЧЕНЬ чувствительное к производительности приложение, и мне интересно, смогу ли я сохранить некоторые константы для связи. У меня есть ряд глобальных констант, которые я использую (например, измерения симуляции), которые используют безумное количество. Я попытался изменить их с констант на переменные, и производительность резко упала. Таким образом, я создал несколько запутанную систему, которая назначает константы из файла конфигурации и явно создает исполняемый файл для запрошенного набора параметров. Таким образом, я хотел бы свести к минимуму объем работы, которую я перестраиваю для каждого изменения параметра.

Вопрос в том, смогу ли я предварительно скомпилировать некоторые из моих объектов и вставить значения во время ссылки. Наиболее вероятная реализация, которую я могу придумать для этого, заключалась бы в том, чтобы включить эти константы в качестве const аргументов для функции, которая нуждается в них, и надеяться, что оптимизация компилятора / компоновщика приведет к той же производительности, что и их жестко закодированные как #define константы , Любые предложения о том, как сделать эту работу?

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

Ответы [ 3 ]

4 голосов
/ 18 марта 2012

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

В случае clang, я рекомендую аналогичный подход, но вместо использования обычного LTO скомпилируйте в битовый код, используя -emit-llvm -c, и компилируйте только в собственный код в качестве последнего шага при компоновке.

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

3 голосов
/ 18 марта 2012

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

Может бытьЕсть много причин для ускорения, если у вас есть константы:

  • небольшие целочисленные константы могут переходить к немедленным операциям сборки
  • Компилятор может выполнять развертывание цикла
  • там можетбудьте особыми арифметическими приемами, если константа имеет степень 2

С другой стороны, вы можете получить замедление, если передаете указатель на const в вашу функцию, и компилятор не может исключить, что вашconst квалифицированный объект является псевдонимом.const только говорит, что вы не имеете права изменять значение, но компилятор не может знать, изменилось ли оно неожиданно.Здесь может помочь объявление указателя с помощью restrict.

Так что определите проблемные места, сравните их в ассемблере с двумя разными версиями (константы и const квалифицированные переменные) и попытайтесь найти причину замедления.

Используйте inline, чтобы аккуратно оптимизировать проблемные места.

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

2 голосов
/ 18 марта 2012

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

Звучит как интересная проблема, в наши дни не так много возможностей для оптимизации настоящего мужика с волосатыми грудями:)

...