Программирование больших вычислительных задач на современном Фортране с использованием компиляторов Intel

Настройки, оптимизация*

Показывать лекцию целиком

Презентацию к лекции Вы можете скачать здесь.

Роль компилятора

Получение кода максимально эффективного для используемого вычислительного комплекса.

Требования к программе

  • Легкая читаемость и модифицируемость
  • Легкая отладка
  • Быстрота исполнения
  • Разработчику необходимы

  • Надежная среда разработки
  • Разные уровни отладки и быстродействия
  • Возможность получать высокоэффективный код
  • Компилятор должен удовлетворить эти требования.

    Настройки проекта

    General – Общие (дополнительные папки, оптимизация, формат отладочной информации)
    Optimization – Оптимизация (подробное описание)
    Debugging – Отладка, включая инструменты для параллельных программ
    Preprocessor – Настройка препроцессора (до компиляции)
    Code Generation – Генерация кода с учетом архитектуры используемых процессоров
    Language – Особенности Fortran 66, 77, 2003, настройка OpenMP, MPI, CoArray.
    Compatibility – Совместимость с ранними версиями языка Fortran и его расширениями
    Diagnostics – Уровни диагностики (уровни автопараллелизации, векторизации, проверка интерфейсов)
    Data – Настройка типов данных
    Floating Point – Контроль чисел с плавающей точкой
    External Procedures – Работа с внешними процедурами
    Output Files – Выходные файлы (листинг, ассемблерный код, объектные файлы)
    Libraries – Библиотеки (portlib, mkl)
    Command Line – Общий вид командной строки

    Оптимизация проекта

    Optimization

    /Od – Отсутствие оптимизации (для режима отладки)
    /O1 – Оптимизация размера исполняемой программы
    /O2 – Максимальная скорость выполнения
    /O3 – Задействует /O2 и, более агрессивные методы оптимизации (подстановка скаляров, раскрутка циклов, подстановка кода для исключения ветвлений).

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

    Loop Unroll Count

    Установка максимального числа раскруток циклов.

    /Qunroll[:n] n - число раскруток, начиная с самого внутреннего цикла.
    /Qunroll:0 - отключение раскрутки.
    /Qunroll - выбор числа раскруток на усмотрение компилятора (значение по умолчанию).

    Parallelization

    Циклы – наиболее трудоемкие места в программе. Включение автопараллелизации для циклов.

    Yes - /Qparallel
        

    Threshold For Auto-Parallelization

    /Qpar-threshold[[:]n]
        

    Устанавливает порог для автопараллелизации циклов на основе вероятности повышения производительности. (Опция /Qparallel должна быть включенной)

    n=0 - автопараллелизация независима от объёма вычислений
    n=100 – циклы распараллелены если имеется 100% прирост производительности
    n=1..99 – процентная вероятность повышения производительности при автопараллелизации

    Threshold For Vectorization

    /Qvec-threshold[[:]n]
        

    Устанавливает порог для векторизации циклов на основе вероятности повышения производительности.

    Полезна для циклов, объем работы вычислений которых не может быть определен во время компиляции.

    do while (delta < 1.0E-4)
      вычисления
    end do
        
    n=0 - всегда выполнять векторизацию
    n=100 – циклы векторизованы если имеется 100% прирост производительности
    n=1..99 – процентная вероятность повышения производительности при векторизации

    Prefetch Insertion

    /Qopt-prefetch[=n]
        

    Оптимизация вставки упреждающей выборки. Уменьшение неудачных обращений в кэш. Требует опции "/O3" в разделе "Optimization" и "/QxSSSE3".

    Minimum (/Qopt-prefetch = 1)
    Medium (/Qopt-prefetch = 2)
    Aggressive (/Qopt-prefetch = 3)
        

    I/O Buffering

    /assume:[no]buffered_io
        

    Установка буферизованного ввода / вывода. Ускоряет работу с жестким диском. Актуально при вводе / выводе больших массивов данных.

    Heap Arrays

    /heap-arrays[[:]n]
        

    Размещение временных массивов минимального размера n (в килобайтах) на "куче", а не на стеке.

    Значение 0 - всегда выделять на "куче".
    Значение 10 – массивы меньшие 10 килобайт размещать в стеке, большие или равно в "куче".
    recursive subroutine f( n )
      integer :: n
      real :: x ( n )     ! размещение в "куче"
      real :: y ( 1000 )  ! размещение в стеке
        

    Interprocedural Optimization

    Single-file (/Qip)
    Multi-file (/Qipo)
        

    Межпроцедурная оптимизация по одному или нескольким файлам.

    Enables MM Library Call

    No (/Qopt-matmul-)
    Yes (/Qopt-matmul)
        

    Замена операции матричного умножения процедурами из библиотек поточной обработки.

    Использование библиотеки обычно обеспечивают лучшую производительность.

    Опция идет по умолчанию в /O3 вместе с /Qparallel

    Директивы

    Специальные инструкции включаемые в программу и управляющие компиляцией.

    Директивы имеют высший приоритет по сравнению с опциями компилятора.

    Воздействие только на часть кода программы.

    Директивы начинаются со знака $, !MS$, !DEC$

    Контроль исходного кода

    Директивы $STRICT и $NOSTRICT.

    $STRICT - использовать только стандарт
    $NOSTRICT - позволяет использовать расширения Intel Fortran Compiler (по умолчанию)

    Записываются в верхней части программной единицы: головной программе, внешней процедуре или модуле.

    Формат исходного кода

    Директивы $FREEFORM и $NOFREEFORM.

    $FREEFORM – свободная форма кода
    $NOFREEFORM – фиксированный формат

    1 символ $ или !MS$ (директивы) *, С или ! - комментарии
    1-5 метки операторов
    6 символ продолжения (не ноль)
    7-72 операторы
    73 и выше игнорируются

    Директива $FIXEDFORMLINESIZE установка длины строки фиксированного формата $FIXEDFORMLINESIZE:72 или 80 или 132

    Условная компиляция

    Директивы $DEFINE и $UNDEFINE.

    $DEFINE – создание символической переменной
    $UNDEFINE – удаление созданной переменной
    !DEC$DEFINE symbol = value
        

    Символическая переменная локальна, т.е. недоступна в программе. Используется вместе с директивами $IF и $IF DEFINED

    Директивы $IF и $IF DEFINED.

    $IF – условная компиляция
    !DEC$IF (условие)
      операторы
    !DEC$ELSEIF (условие)
      операторы
    !DEC$ELSE
      операторы 
    !DEC$ENDIF
        
    $IF DEFINED(переменная) – проверка определения директивой $DEFINE
    program prog
    
      !DEC$DEFINE PARAM = 2
    
      !DEC$IF (PARAM == 1)
        write(*,*) "Use numerical algorithm N 1 " 
      !DEC$ELSE
        write(*,*) "Use numerical algorithm N 2 " ! *****
      !DEC$ENDIF   
    
      !DEC$UNDEFINE PARAM
    
      !DEC$IF DEFINED(PARAM)
        write(*,*) "Use numerical algorithm....." ! *****
      !DEC$ELSE
        write(*,*) "No algorithm ................"
      !DEC$ENDIF
    
    end
        

    Управление отладкой

    Директивы $DECLARE и $NODECLARE.

    $DECLARE – предупреждения для необъявленных переменных (implicit none)
    $NODECLARE – отмена предупреждений

    Директива $MESSAGE вывод символьной строки во время компиляции

    !DEC$MESSAGE: "Компиляция графической части"
        

    для программ занимающих значительной время компиляции

    Разновидности типа

    Директивы $INTEGER и $REAL.

    $INTEGER: 2, 4 или 8 – как объявлены переменные в операторе integer Распространяется на разновидности типа logical.
    $REAL: 4, 8 или 16 – как объявлены переменные в операторе real Распространяется на разновидности типа complex.

    Листинг исходного кода

    Директива $TITLE вывод специального заголовка на каждой странице листинга кода программы.

    Директива $SUBTITLE вывод специального подзаголовка на каждой странице листинга кода программы.

    Работают при включенной опции Source Listing

    Подключение библиотеки

    Директива $OBJCOMMENT LIB: имя библиотеки помещает полное имя библиотеки с указанием пути в объектный файл.

    program prog
    
    !DEC$OBJCOMMENT LIB: "mkl_blas95.lib"
    ! или
    ! !DEC$OBJCOMMENT LIB: "D:\Intel\mkl\lib\ia32\mkl_blas95.lib"
    
      use mkl95_blas
      integer, parameter :: n = 5    ! количество элементов
      real :: a(n) = (/1,2,3,4,5/), ! векторы
              b(n) = (/2,4,6,8,9/)  
      real res
      res = dot(a,b) ! скалярное произведение
      write(*,*) "Scalar product = ", res
    
    end
        
    Вернуться к учебному плану