Встроенная функция (программирование)

В программном обеспечении, в теории компиляторов, встроенная функция (англ. англ. 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 чисел с плавающей запятой

[7]

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. 1 2 Intel® C++ Compiler 19.1 Developer Guide and Reference (англ.). Intel® C++ Compiler Documentation (16 декабря 2019). Дата обращения: 17 января 2020.
  2. The Clang Team. Clang Language Extensions (англ.). Clang 11 documentation (2020). — «Builtin Functions». Дата обращения: 17 января 2020.
  3. MSDN. Compiler Intrinsics (англ.). Microsoft. Дата обращения: 20 июня 2012.
  4. GCC documentation. Built-in Functions Specific to Particular Target Machines (англ.). Free Software Foundation. Дата обращения: 20 июня 2012.
  5. Vector Extensions (англ.). Using the GNU Compiler Collection (GCC). Дата обращения: 16 января 2020.
  6. Sony open sources Vector Math and SIMD math libraries (Cell PPU/SPU/other platforms). Beyond3D Forum (амер. англ.). Архивировано из оригинала 24 июня 2016. Дата обращения: 17 января 2020.
  7. Intel Intrinsics
  8. Mok, Kris. Intrinsic Methods in HotSpot VM (англ.). Slideshare (25 февраля 2013). Дата обращения: 20 декабря 2014.
  9. ANSI X3 Committee. American National Standard programming language PL/I. — 1976.
  10. IBM Corporation. IBM PL/I for MVS & VM Language Reference. — 1995. — P. 337–338.

Ссылки