C/C++ использование специальных функций процессора
Мне любопытно, используют ли новые компиляторы некоторые дополнительные функции, встроенные в новые процессоры, такие как MMX SSE,3DNow! так что?
Я имею в виду, что в оригинальном 8086 даже не было FPU, так что компилятор, который старый не может даже использовать, но новые компиляторы могут, так как FPU является частью каждого нового процессора. Итак, новые компиляторы используют новые функции процессора?
Или, должно быть, правильнее спросить, используют ли новые функции стандартной библиотеки C/C++ новые функции?
Спасибо за ответ.
РЕДАКТИРОВАТЬ:
Итак, если я вас всех правильно понял, даже некоторые стандартные операции, особенно с плавающими числами, могут быть выполнены с использованием SSE быстрее.
Чтобы использовать его, я должен включить эту функцию в моем компиляторе, если он ее поддерживает. Если это так, я должен быть уверен, что целевая платформа поддерживает эти функции.
В случае некоторых системных библиотек, которые требуют высочайшей производительности, таких как OpenGL, DirectX и т. Д., Эта поддержка может поддерживаться в системе.
По умолчанию по причинам совместимости компилятор не поддерживает его, но вы можете добавить эту поддержку, используя специальные функции C, предоставляемые, например, Intel. Это должно быть наилучшим способом, поскольку вы можете напрямую контролировать, когда вы используете специальные функции нужной платформы, и писать приложения с поддержкой нескольких ЦП.
9 ответов
gcc будет поддерживать новые инструкции через аргументы командной строки. Смотрите здесь для получения дополнительной информации. Цитировать:
GCC может воспользоваться дополнительными инструкциями в расширениях MMX, SSE, SSE2, SSE3 и 3dnow последних процессоров Intel и AMD. Опции -mmmx, -msse, -msse2, -msse3 и -m3dnow позволяют использовать эти дополнительные инструкции, позволяя параллельно обрабатывать несколько слов данных. Получающиеся исполняемые файлы будут работать только на процессорах, поддерживающих соответствующие расширения - в других системах они будут аварийно завершаться с ошибкой недопустимой инструкции (или аналогичной)
Эти инструкции не являются частью каких-либо стандартов ISO C/C++. Они доступны через встроенные функции компилятора, в зависимости от используемого компилятора.
Для MSVC см. http://msdn.microsoft.com/en-us/library/26td21ds(VS.80).aspx
Для GCC вы можете посмотреть на http://developer.apple.com/hardwaredrivers/ve/sse.html
AFAIK, SSE присущи одинаковы между GCC и MSVC.
Компиляторы будут стремиться создавать код для минимального набора функций в процессоре. Они также предоставляют ключи компиляции, которые позволяют вам ориентироваться на конкретные процессоры. Таким образом, они могут продавать больше компиляторов (тем, у кого старые процессоры, а также модным людям с новыми).
Вам нужно будет изучить документацию, прилагаемую к вашему компилятору.
Если вы используете компилятор Intel C и установите достаточно высокие параметры оптимизации, вы обнаружите, что некоторые из ваших циклов "векторизованы", что означает, что компилятор переписал их для использования инструкций в стиле SSE.
Если вы хотите использовать операции SSE напрямую, вы используете встроенные функции, определенные в заголовочном файле 'xmmintrin.h'; сказать
#include
__m128 U, V, W; float ww [4];
V = _mm_set1_ps (1.5);
U = _mm_set_ps (0,1,2,3);
W = _mm_add_ps (U, V);
_mm_storeu_ps (WW,W);
Иногда библиотека времени выполнения будет содержать несколько реализаций функции, и библиотека будет динамически выбирать между реализациями при запуске программы. Затраты могут быть связаны с вызовом указателя на функцию вместо прямого вызова функции, но при использовании оптимизированной функции для конкретного процессора выгода может быть намного выше.
JIT-компиляторы (для языков ВМ, таких как Java и C#) делают еще один шаг и компилируют байт-код для конкретного процессора, на котором он работает. Это дает вашему собственному коду преимущество конкретной оптимизации процессора. Это одна из причин, почему Java-код может на самом деле быть быстрее, чем скомпилированный C-код, потому что JIT-компилятор Java может откладывать свои решения по оптимизации до тех пор, пока программа не будет запущена на реальной целевой машине. Компилятор переменного тока должен принимать эти решения, не всегда зная, каков целевой процессор. Кроме того, JIT-компиляторы развиваются и могут со временем сделать вашу программу быстрее, без необходимости что-либо делать.
Если вы говорите о коде, написанном на C/C++, новые функции будут недоступны, если вы скажете так своему компилятору. По умолчанию ваш компилятор, вероятно, нацелен на "обычный x86" (естественно, с FPU:)), обычно оптимизированный для наиболее распространенного поколения процессоров на данный момент, но все же способный работать на более старых процессорах.
Если вы хотите, чтобы компилятор генерировал код, также учитывающий новые наборы команд, вы должны указать ему сделать это с соответствующим параметром командной строки / параметром проекта, например, для Visual C++ опция включения генерации инструкций SSE/SSE2 - / arch.
Обратите внимание, что многие функции новых наборов команд не могут быть использованы непосредственно в "нормальном" коде, поэтому вам обычно предоставляют встроенные функции компилятора для работы с конкретными типами данных, родными из новых наборов команд.
Корпорация Intel предоставляет обновленный пример кода CPUID каждый раз, когда выпускает новый процессор, так что вы можете проверить наличие новых функций, и это было, насколько я помню. По крайней мере, это то, что я обнаружил, когда впервые задумался над этим же вопросом.
Использование CPUID для обнаружения наличия инструкций SSE 4.1 и SSE 4.2
По мере выпуска новых компиляторов они добавляют новые функции, например, например, VS2010. Генерация кода в Visual C++ в Visual Studio 2010
Различные компиляторы будут использовать различные новые функции. Visual Studio будет использовать SSE/2, и я верю, что компилятор Intel будет поддерживать самые последние функции процессора. Вы, конечно, должны с осторожностью относиться к проникновению на рынок вашей любимой функции.
Что касается того, что ваша любимая стандартная библиотека использует, это зависит от того, с чем она была скомпилирована. Однако стандартная библиотека C++ обычно компилируется на месте, так как она очень сильно шаблонизирована, поэтому, если вы включаете SSE2, библиотеки C++ std должны использовать ее. Что касается ЭЛТ, зависит от того, с чем они были скомпилированы.
Как правило, есть два способа, которыми компилятор может генерировать код, который использует специальные функции, подобные этим:
- Когда сам компилятор компилируется, вы конфигурируете его для генерации кода для конкретной архитектуры, и он может использовать любые функции, которые он знает, которые будут иметь архитектура. Например, если это
gcc
сконфигурирован для достаточно нового процессора Intel (или "недостаточно старого"?), чтобы содержать встроенный FPU, он будет генерировать инструкции с плавающей запятой. - Когда вызывается компилятор, флаги или параметры могут указывать тип функций, доступных процессору, который будет запускать программу, и тогда компилятор будет знать, что эти функции безопасно использовать. Если флаги отсутствуют, он сгенерирует эквивалентный код без использования специальных инструкций, предоставляемых этими функциями.