Россия, Липецк, Липецкий Государственный Технический Университет, 2014 |
Компиляторы Intel. Возможности автоматической оптимизации
Векторизация
AVX – набор векторных команд
Intel® AVX (Advanced Vector Extensions) расширяет возможности 128-разрядных векторных регистров XMM (16 регистров), позволяя использовать 256-разрядные векторы. 256 разрядов используются в операциях с плавающей точкой.
В других операциях используются младшие 128 разрядов.
В AVX операнды и результат операции отделены друг от друга. Это позволяет оптимизировать использование регистров, генерировать более компактный код, уменьшить количество зависимостей т.д.
AVX для архитектуры Sandy Bridge
Поддержка векторных конструкций в Intel® CilkTM Plus и Array Building Blocks.
Поддержка прагм и "интринсиков" (низкоуровневые возможности).
Поддержка сложных условных выражений.
Улучшенная поддержка смешения типов в одном цикле.
Поддержка операций с насыщением.
Отчёты об оптимизации
Отчёты об оптимизации
- /Qvec-report - генерация протокола векторизации (что векторизовано, что нет и почему).
- /Qpar-report - генерация протокола распараллеливания.
- /Qopt-report - генерация протокола оптимизации.
Профилирование на уровне циклов
Сбор статистики по циклам и функциям
- /Qprofile-loops:all - сбор статистики.
- LoopProfileViewer - утилита для просмотра отчётов.
- GAP - Guided Auto Parallelism (направляемая автопараллелизация).
- /Qguide (-guide) - запуск анализа.
- Не порождает параллельный код, но даёт рекомендации.
Оптимизация в примерах
- Отключение оптимизации
- Подразумевается в режиме Debug в MS Visual Studio
- Глобальная оптимизация
- Не увеличивает размер кода
- Увеличивает размер кода
- Оптимизация времени выполнения
- Опция по умолчанию
- Подстановки в коде
- Развертывание циклов
- Векторизация
- Высокоуровневая оптимизация.
- Оптимизирующие преобразования уровня /O2 + более агрессивные методы.
- Улучшенная векторизация.
- Более полный учёт свойств циклов и массивов.
- Оптимизация циклов: разделение циклов (loop distribution), перестановка циклов (loop interchange), слияние циклов (loop fusion), развёртка циклов (loop unrolling).
- Подстановка кода в ветвлениях.
- Оптимизация под размер кэша.
- Предвыборка и предсказания ветвления.
- Возможна большая эффективность в приложениях, включающих обработку больших массивов.
Пример 1
Matrices.cpp
#include <ctime> #include <iostream> #include "stdlib.h" #include "conio.h" #include "math.h" using namespace std; const int SIZE = 1000; void matrixMultiply(double ** matrA, double ** matrB, double ** matrC, int matrSize); double sinCosMultiply(double i, double j); int main() { time_t t1, t2; double trace(0); double ** matrixA = new double*[SIZE]; double ** matrixB = new double*[SIZE]; cout << "We will construct the square matrix " << SIZE << "x" << SIZE << endl; cout << "of pseudo-random values" << endl; cout << "and multiply it by itself. Then we will find the trace of the matrix." << endl; for(int i = 0; i < SIZE; i++) { matrixA[i] = new double[SIZE]; matrixB[i] = new double[SIZE]; } t1 = clock(); for(int i=0; i<SIZE; i++) { for(int j=0; j<SIZE; j++) { matrixA[i][j]=sinCosMultiply(rand()%10/3, rand()%10/3); }} matrixMultiply(matrixA, matrixA, matrixB, SIZE); for(int i=0; i<SIZE; i++) { for(int j=0; j<SIZE; j++) { if(i==j) trace += matrixB[i][j]; } } t2 = clock(); cout << "\nTrace is " << trace << endl; cout << "\nInitial clock ticks value is " << t1 << endl; cout << "Final clock ticks value is " << t2 << endl; cout << "Difference in clock ticks is " << difftime(t2,t1) << endl; cout << "Clock ticks per second value is " << CLOCKS_PER_SEC << endl; cout << "\nActual time of calculations is " << ((t2-t1)/CLOCKS_PER_SEC) << " sec" << endl; for(int i = 0; i < SIZE; i++) { delete [] matrixA[i]; delete [] matrixB[i]; } delete [] matrixA; delete [] matrixB; return 0; } void matrixMultiply(double ** matrA, double ** matrB, double ** matrC, int matrSize) { for(int i=0; i<matrSize; i++) { for(int j=0; j<matrSize; j++) { matrC[i][j] = 0; for(int k=0; k<matrSize; k++) { matrC[i][j] += matrA[i][k]*matrB[k][j]; } } } } double sinCosMultiply(double i, double j) { return sin(i)*cos(j); }
Подготовим тест:
- icl /FeMatricesOd /Od Matrices.cpp
- icl /FeMatricesO1 /O1 Matrices.cpp
- icl /FeMatricesO2 /O2 Matrices.cpp
- icl /FeMatricesO3 /O3 Matrices.cpp
Intel Core 2 Duo T3700 2.00 ГГц, 2 Гб RAM
Среднее значение времени выполнения:
- MatricesOd . . . 21.76 с.
- MatricesO1 . . . 14.05 с.
- MatricesO2 . . . 9.63 с.
- MatricesO3 . . . 9.57 с.
Вопрос. Объясните результаты теста.