2013-04-17 3 views
3

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

Флаги, которые я нашел до сих пор, которые улучшают код матрицы.

-O3/O4 
-funroll-loops 
-ffast-math 

ответ

14

Прежде всего, я не рекомендую использовать -ffast-math по следующим причинам:

  1. Было доказано, что производительность на самом деле деградирует когда используя этот параметр в большинстве (если не все). Итак, "fast math" есть нет на самом деле это быстро.

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

  3. Вы можете получить разные результаты в разных условиях, и разница может быть . Термин «среда» (в данном случае) подразумевает комбинацию: аппаратного обеспечения, ОС, компилятор. Это означает, что разнообразие ситуаций, когда вы можете получить неожиданные результаты, имеет экспоненциальный рост.

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

  5. Наконец, взгляните на this article.

По тем же причинам следует избегать -Ofast (как она включает в себя зло -ffast-math). Экстракт:

-Ofast

Игнорирование строгое соблюдение стандартов. -Ofast позволяет оптимизировать все -O3. Он также позволяет оптимизировать, которые недействительны для всех стандартных программ. Включается -ffast-math и Fortran-specific -fno-protect-parens и -fstack-arrays.

Флаг такого типа, как -O4. По крайней мере, я не знаю об этом, и в официальной документации GCC нет никаких следов. Таким образом, максимум в этом отношении - -O3, и вы должны определенно использовать его, а не только для оптимизации математики, но и для сборки релизов в целом.

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

Я могу порекомендовать еще 2 флага: -march=native и -mfpmath=sse. Аналогично -O3, -march=native хорош в целом для выпуска сборок любого программного обеспечения, а не только для интенсивной математики. -mfpmath=sse позволяет использовать регистры XMM в инструкциях с плавающей запятой (вместо стека в x87 mode).

Кроме того, я хотел бы сказать, что жаль, что вы не хотите изменять свой код, чтобы получить лучшую производительность, поскольку это основной источник ускорения для векторных/матричных подпрограмм. Благодаря SIMD, SSE Intrinsics и Vectorization код тяжелой линейной алгебры может быть на порядок быстрее, чем без них. Тем не менее, правильное применение этих методов требует глубокого знания их внутренних компонентов и довольно много времени/усилий, чтобы изменить (фактически переписать) код.

Тем не менее, существует один вариант, который может быть подходящим для вашего случая. GCC предлагает auto-vectorization, который может быть включен по номеру -ftree-vectorize, но он не нужен, поскольку вы используете -O3 (потому что он включает в себя -ftree-vectorize). Дело в том, что вы все равно должны помочь GCC немного понять, какой код можно авто-векторизовать. Модификации обычно незначительны (при необходимости вообще), но вы должны быть знакомы с ними. См. Раздел Vectorizable Loops по ссылке выше.

Наконец, я рекомендую вам ознакомиться с библиотекой на основе шаблонов на C++, которая имеет высокоэффективную реализацию наиболее распространенных подпрограмм линейной алгебры Eigen. Он использует все техники, упомянутые здесь до сих пор очень умным способом. Интерфейс является чисто объектно-ориентированным, опрятным и приятным в использовании. Объектно-ориентированный подход очень важен для линейной алгебры, поскольку он обычно манипулирует чистыми объектами, такими как матрицы, векторы, кватернионы, вращения, фильтры и т. Д. В результате при программировании с Eigen вам никогда не придется самостоятельно разбираться с такими концепциями низкого уровня (как SSE, Vectorization и т. Д.), А просто наслаждаться решением вашей конкретной проблемы.

+2

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

+0

Спасибо! Это очень помогло. Я действительно пытаюсь сравнить лучшее ускорение, которое дает оптимизированный компилятор код (это мой вопрос) с моим оптимизированным вручную кодом для операций с матрицами. – laxy

+1

@ Харооган: спасибо за этот совет. Я полностью принимаю ваш ответ :). Мне жаль, что я еще не могу продвинуться. – laxy

Смежные вопросы