Встроенная функция (программирование)
В программном обеспечении, в теории компиляторов, встроенная функция (англ. англ. intrinsic function или англ. built-in function) — функция, доступная для использования в данном языке программирования, реализация которой обрабатывается компилятором особым образом. Как правило, он может заменять исходный вызов функции на последовательность автоматически сгенерированных инструкций, подобно встраиваемой функции[1]. В отличие от встраиваемой функции, компилятор обладает «глубоким знанием» о встроенной функции и, таким образом, может лучше интегрировать и оптимизировать её для конкретной ситуации.
Компиляторы, реализующие встроенные функции, могут активировать их только тогда, когда программа запрашивает оптимизацию, в противном случае используя реализацию по умолчанию, предоставляемую системой времени выполнения языка.
Векторизация и распараллеливание
Встроенные функции часто используются для явной реализации векторизации и распараллеливания в языках, которые не поддерживают такие конструкции. Некоторые API, например, AltiVec и OpenMP, используют встроенные функции для объявления, соответственно, векторизуемых и поддерживающих многопроцессорную обработку операций во время компиляции. Компилятор анализирует встроенные функции и преобразует их в векторные математические или многопроцессорные объектные коды, соответствующие целевой платформе. Некоторые встроенные функции используются для предоставления дополнительных ограничений оптимизатору, например, значения, которые переменная не может принимать[2].
По языкам программирования
C и C++
Компиляторы для языков C и C++ от Microsoft[3], Intel[1] и GCC[4] реализуют встроенные функции, которые напрямую отображаются на инструкции x86 типа SIMD (один поток команд, множество потоков данных) (MMX, SSE, SSE2, SSE3, SSSE3, SSE4, AVX, AVX2, AVX-512, FMA и т. д.). Встроенные функции позволяют отображать код на стандартные ассемблерные инструкции, которые обычно недоступны через C/C++; например, сканирование битов и параллельные операции над 128-битными (SSE) и 256-битными (AVX) данными.
Некоторые компиляторы C и C++ предоставляют непереносимые, платформенно-зависимые встроенные функции. Другие встроенные функции (например, встроенные функции GNU) являются более абстрактными, аппроксимируя возможности нескольких современных платформ, и имеют переносимые резервные реализации (fall back) для платформ без соответствующих инструкций[5]. Для библиотек C++, таких как glm или библиотеки векторной математики от Sony[6], распространена практика достижения переносимости с помощью условной компиляции (на основе специфичных для платформы флагов компилятора). Это позволяет предоставлять полностью переносимые высокоуровневые примитивы (например, тип четырёхэлементного вектора с плавающей запятой), отображённые на соответствующие реализации на низкоуровневых языках, сохраняя при этом преимущества системы типов C++ и встраивания; отсюда и преимущество перед компоновкой с объектными файлами, написанными вручную на ассемблере, с использованием двоичного интерфейса приложений (ABI) языка C.
Примеры
Ниже приведены примеры сигнатур встроенных функций из набора Intel.
uint64_t __rdtsc (); // возвращает внутренний счётчик тактов процессора
uint64_t __popcnt64 (uint64_t n); // подсчитывает количество установленных битов в n
uint64_t _umul128 (uint64_t Factor1, uint64_t Factor2, uint64_t* HighProduct); // умножение 64 бит * 64 бит => 128 бит
__m512 _mm512_add_ps (__m512 a, __m512 b); // вычисляет a + b для двух векторов из 16 чисел с плавающей запятой
__m512 _mm512_fmadd_ps(__m512 a, __m512 b, __m512 c); // вычисляет a*b + c для трёх векторов из 16 чисел с плавающей запятой
COBOL
Модуль встроенных функций для COBOL был введён в стандарте ANSI INCITS X3.23a-1989 / ISO 1989:1985/Amd 1:1992.
Java
JIT-компилятор виртуальной машины Java (JVM) HotSpot также имеет встроенные функции для определённых API Java[8]. Встроенные функции HotSpot — стандартные API Java, которые могут иметь одну или несколько оптимизированных реализаций на некоторых платформах.
PL/I
Стандарт ANSI/ISO для языка PL/I определяет около 90 встроенных функций[9]. Их принято группировать следующим образом[10]:
- Встроенные функции для обработки строк, такие как INDEX, LENGTH
- Арифметические встроенные функции, такие как ABS, CEIL, ROUND
- Математические встроенные функции, такие как SIN, COS, LOG, ERF
- Встроенные функции для обработки массивов, например ANY, ALL, PROD
- Встроенные функции для обработки условий, такие как ONCODE, ONFILE
- Встроенные функции управления памятью, например ADDR, POINTER
- Встроенные функции ввода-вывода: LINENO
- Прочие встроенные функции, такие как DATE и TIME
Отдельные компиляторы добавляли дополнительные встроенные функции, специфичные для архитектуры машины или операционной системы.
Встроенная функция идентифицируется, если её имя не объявляется и используется по умолчанию, или если она объявляется с атрибутом `BUILTIN`. Предоставленная пользователем функция с тем же именем может быть подставлена, если объявить её как `ENTRY`.
Примечания
- ↑ 1 2 Intel® C++ Compiler 19.1 Developer Guide and Reference (англ.). Intel® C++ Compiler Documentation (16 декабря 2019). Дата обращения: 17 января 2020.
- ↑ The Clang Team. Clang Language Extensions (англ.). Clang 11 documentation (2020). — «Builtin Functions». Дата обращения: 17 января 2020.
- ↑ MSDN. Compiler Intrinsics (англ.). Microsoft. Дата обращения: 20 июня 2012.
- ↑ GCC documentation. Built-in Functions Specific to Particular Target Machines (англ.). Free Software Foundation. Дата обращения: 20 июня 2012.
- ↑ Vector Extensions (англ.). Using the GNU Compiler Collection (GCC). Дата обращения: 16 января 2020.
- ↑ Sony open sources Vector Math and SIMD math libraries (Cell PPU/SPU/other platforms). Beyond3D Forum (амер. англ.). Архивировано из оригинала 24 июня 2016. Дата обращения: 17 января 2020.
- ↑ Intel Intrinsics
- ↑ Mok, Kris. Intrinsic Methods in HotSpot VM (англ.). Slideshare (25 февраля 2013). Дата обращения: 20 декабря 2014.
- ↑ ANSI X3 Committee. American National Standard programming language PL/I. — 1976.
- ↑ IBM Corporation. IBM PL/I for MVS & VM Language Reference. — 1995. — P. 337–338.
Ссылки
- Intel Intrinsics Guide (англ.)
- Using milicode routines, документация IBM AIX 6.1 (англ.)