Поддерживаемые MCST директивы #pragma и !dir$

Общая информация

В данном документе описываются только собственные директивы #pragma и !dir$. Директивы #pragma, описанные в каких-либо стандартах, описаны в статье Поддерживаемые стандартные директивы #pragma. Те директивы #pragma, которые позаимствованы у gcc, описаны в статье Поддерживаемые GNU директивы #pragma

Директивы #pragma языков C/C++

Директивы #pragma для заголовочных файлов

#pragma once

Запрет повторного включения заголовочного файла. По действию сходно с include guard. Добавляется в самое начало файла

Директивы #pragma для управления диагностическими сообщениями

Настроить можно только те диагностические сообщения, которые являются предупреждением (warning) или замечанием (remark). Под <msg> подразумевается номер диагностического сообщения, который печатается в компиляторе при выдаче

#pragma diag_suppress <msg>

Подавить вывод диагностического сообщения

#pragma diag_remark <msg>

Поменять уровень диагностического сообщения на “замечание”

#pragma diag_warning <msg>

Поменять уровень диагностического сообщения на “предупреждение”

#pragma diag_error <msg>

Поменять уровень диагностического сообщения на “ошибка”

#pragma diag_default <msg>

Установить для диагностического сообщения поведение по умолчанию

#pragma diag_once <msg>

Установить для диагностического сообщения режим, в котором оно выдается не более одного раза

#pragma diagnostic push

Сохранить текущие настройки диагностических сообщений в виртуальный стек

#pragma diagnostic pop

Извлечь настройки диагностических сообщений из виртуального стека

Директивы #pragma для оптимизации ассемблерных вставок

#pragma asm_inline
#pragma no_asm_inline

Управление inline-подстановкой ассемблерных вставок

#pragma asm_length (length)

Доступно только для архитектуры E2K. Указание длительности ассемблерной вставки, выраженной в количестве машинных тактов. Для параметра length учитываются только значения от 0 до 14. Значения 15 и выше игнорируются

Директивы #pragma для оптимизации ассемблерных вставок

#pragma unknown_control_flow (func_name)

Обработка функции func_name аналогично функции setjmp

#pragma no_instrument_function (func_name)

Отказ от инструментирования функции func_name

Директивы #pragma, указывающие компилятору свойства процедур

#pragma no_inline (func_list)

Запрещает компилятору делать inline-подстановку функций в списке

#pragma hot (func_list)

Указывает компилятору, что представленные в списке функции являются “горячими”

#pragma no_side_effect (func_list)

Указывает, что функции не имеют посторонних эффектов (не меняют состояние программы, невидимое в точке вызова). Игнорируется

Директивы #pragma для оптимизации циклов

#pragma unroll (N)

Применить Loop Unrolling на N к ближайшему после объявления директивы циклу. Если параметр опущен, то компилятор это воспринимает, как желание пользователя полностью раскрутить цикл в скалярный код. Дополнительным эффектом применения прагмы является увеличение оценочного количества итераций указанного цикла, если оно не известно точно. Количество итераций вычисляется как min_ovl * N, где min_ovl - минимальное количество итераций, при котором применится оптимизация аппаратного наложения итераций цикла. Для более точного определения количества итераций цикла рекомендуется использовать эту прагму в комбинации с #pragma loop_count (N)

#pragma split_fuse (N)

Игнорируется

#pragma loop count (N)

Установить у ближайшего после объявления директивы цикла количество итераций равное N. Игнорируется, если подан реальный профиль через -fprofile-use

#pragma vector always

Форсирует применение векторизации к ближайшему после объявления директивы циклу, даже если эвристики оптимизации говорят, что её применение нецелесообразно

#pragma vector aligned

Говорит компилятору, что все обращения к памяти в ближайшем после объявления директивы цикле являются выровненными, так что векторизация может примениться к этому циклу более эффективно. Величина выравнивания зависит от целевой архитектуры: для Elbrus V1-V4 это 8 байт, для V5 и далее - 16 байт.

#pragma vector unaligned

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

#pragma vector nontemporal

Запрет заведения в кэш-память всех уровней и включение режима write combining (объединение операций в store-буфере) для операций записи в ближайшем после объявления директивы цикле.

#pragma novector

Запрет применения векторизации к ближайшему после объявления директивы циклу

#pragma reduce recurrence

Форсирует разрыв рекурентностей в ближайшем после объявления директивы цикле

#pragma prefetch

Форсирует включение аппаратной предподкачки данных для регулярных операций чтения из памяти в ближайшем после объявления директивы цикле, даже если эвристики оптимизации говорят, что это нецелесообразно; не влияет на автоматическую генерацию операций программной предподкачки

#pragma noprefetch

Запрет аппаратной предподкачки данных для регулярных операций чтения из памяти в ближайшем после объявления директивы цикле; не влияет на автоматическую генерацию операций программной предподкачки

#pragma comb_oper

Форсирует комбинирование пар арифметических операций в двухэтажные операции в ближайшем после объявления директивы цикле, даже если эвристики оптимизации говорят, что это нецелесообразно

#pragma no_comb_oper

Запрещает комбинирование пар арифметических операций в двухэтажные операции в ближайшем после объявления директивы цикле

#pragma ivdep

Указывает, что в ближайшем после объявления директивы цикле, если для пары операций чтения/записи не удалось статически определить их зависимость или независимость, то следует считать, что межитерационные зависимости для этих операций отсутствуют

#pragma no_dam

Запрещает применение динамического разрыва зависимостей (DAM) к ближайшему после объявления директивы циклу. Может быть полезной в случае, когда в цикле есть maybe-зависимости между операциями доступа к памяти, из-за которых применение DAM приводит к частому уходу на компенсирующий код. Прагма имеет эффект только для архитектуры Elbrus.

#pragma swp

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

#pragma noswp

Запрещает применение оптимизаций конвейеризации к ближайшему после объявления циклу

#pragma spmv

Позиционирует ближайший цикл как цикл умножения разреженных матриц. Это даёт возможность лучше настроить оптимизации и оценки компилятора для указанного цикла

Директивы !dir$ языка Fortran

Директивы !dir$ для оптимизации кода

!dir$ unroll (N)

Применить Loop Unrolling на N к ближайшему после объявления директивы циклу. Дополнительным эффектом применения прагмы является увеличение оценочного количества итераций указанного цикла, если оно не известно точно. Количество итераций вычисляется как min_ovl * N, где min_ovl - минимальное количество итераций, при котором применится оптимизация аппаратного наложения итераций цикла. Для более точного определения количества итераций цикла рекомендуется использовать эту прагму в комбинации с !dir$ loop count (N)

!dir$ loop count (N)

Установить у ближайшего после объявления директивы цикла количество итераций равное N. Игнорируется, если подан реальный профиль через -fprofile-use

!dir$ vector always

Форсирует применение векторизации к ближайшему после объявления директивы циклу, даже если эвристики оптимизации говорят, что её применение нецелесообразно

!dir$ vector aligned

Говорит компилятору, что все обращения к памяти в ближайшем после объявления директивы цикле являются выровненными, так что векторизация может примениться к этому циклу более эффективно. Величина выравнивания зависит от целевой архитектуры: для Elbrus V1-V4 это 8 байт, для V5 и далее - 16 байт.

!dir$ vector unaligned

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

!dir$ vector nontemporal

Запрет заведения в кэш-память всех уровней и включение режима write combining (объединение операций в store-буфере) для операций записи в ближайшем после объявления директивы цикле.

!dir$ novector

Запрет применения векторизации к ближайшему после объявления директивы циклу

!dir$ reduce recurrence

Форсирует разрыв рекурентностей в ближайшем после объявления директивы цикле

!dir$ inline

Рекомендует inline-подстановку всех функций в следующую за директивой строку или в тело следующего за директивой цикла. Обычно компилятор игнорирует такие подсказки, однако, вместе с опциями -finline-only-native или -fforce-inline они могут стать более весомыми.

!dir$ forceinline

Обязывает компилятор произвести inline-подстановку всех функций в следующую за директивой строку или в тело следующего за директивой цикла.

!dir$ noinline

Запрещает компилятору производить inline-подстановку в следующую за директивой строку или в тело следующего за директивой цикла.

!dir$ ivdep

Указывает, что в ближайшем после объявления директивы цикле, если для пары операций чтения/записи не удалось статически определить их зависимость или независимость, то следует считать, что межитерационные зависимости для этих операций отсутствуют

!dir$ no_dam

Запрещает применение динамического разрыва зависимостей (DAM) к ближайшему после объявления директивы циклу. Может быть полезной в случае, когда в цикле есть maybe-зависимости между операциями доступа к памяти, из-за которых применение DAM приводит к частому уходу на компенсирующий код

!dir$ spmv

Позиционирует ближайший цикл как цикл умножения разреженных матриц. Это даёт возможность лучше настроить оптимизации и оценки компилятора для указанного цикла

!dir$ swp

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

!dir$ noswp

Запрещает применение оптимизаций конвейеризации к ближайшему после объявления циклу

!dir$ comb_oper

Форсирует комбинирование пар арифметических операций в двухэтажные операции в ближайшем после объявления директивы цикле, даже если эвристики оптимизации говорят, что это нецелесообразно

!dir$ no_comb_oper

Запрещает комбинирование пар арифметических операций в двухэтажные операции в ближайшем после объявления директивы цикле

!dir$ expect_prob P

Задает вероятность перехода на ветку THEN в операторе IF в следующей за директивой строке. Вероятность P должна быть в диапазоне [0..1]. Это позволяет компилятору лучше настроить оптимизации для данного перехода.

Побочные эффекты оптимизационных директив #pragma и !dir$

Почти все оптимизационные директивы #pragma и !dir$ для циклов приводят к отключению оптимизации Loop Jam (слияние независимых смежных циклов с одинаковым количеством итераций). Это вызвано тем, что во многих случаях после слияния циклов невозможно точно исполнить предписание директив #pragma и !dir$. В число таких директив входят:

  • #pragma unroll (N)

  • #pragma loop count (N)

  • #pragma vector

  • #pragma novector

  • #pragma reduce recurrence

  • #pragma prefetch

  • #pragma noprefetch

  • #pragma comb_oper

  • #pragma ivdep

  • #pragma no_dam

  • #pragma spmv

  • !dir$ unroll (N)

  • !dir$ loop count (N)

  • !dir$ vector

  • !dir$ novector

  • !dir$ reduce recurrence

  • !dir$ comb_oper

  • !dir$ ivdep

  • !dir$ no_dam

  • !dir$ spmv