ISSN0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
TECHNICAL SCIENCE. 2017. No 3
УДК 004.4'422 DOI: 10.17213/0321-2653-2017-3-56-63
ЭФФЕКТИВНОСТЬ АВТОМАТИЧЕСКОЙ ВЕКТОРИЗАЦИИ ЦИКЛОВ НА АРХИТЕКТУРАХ INTEL 64 И INTEL XEON PHI*
© 2017 г. О.В. Молдованова, М.Г. Курносое
Сибирский государственный университет телекоммуникаций и информатики, г. Новосибирск, Россия
EFFICIENCY ANALYSIS OF VECTORIZING COMPILERS FOR INTEL 64 AND INTEL XEON PHI ARCHITECTURES
O.V. Moldovanova, M.G. Kurnosov
Siberian State University of Telecommunications and Information Sciences, Novosibirsk, Russia
Молдованова Ольга Владимировна - канд. техн. наук, Moldovanova Olga Vladimirovna - Candidate of Technical
доцент, кафедра «Вычислительные системы», Сибирский Sciences, assistant professor, department « Computing system »,
государственный университет телекоммуникаций и инфор- Siberian State University of Telecommunications and
матики, инженер-программист, Лаборатория вычислитель- Information Sciences, advanced programmer engineer, Labora-
ных систем, Институт физики полупроводников tory of Computer Systems, Rzhanov Institute of Semiconductor
им. А.В. Ржанова СО РАН, г. Новосибирск, Россия. Physics of Siberian Branch of Russian Academy of Sciences,
E-mail: ovm@sibguti.ru Novosibirsk, Russia. E-mail: ovm@sibguti.ru
Курносов Михаил Георгиевич - канд. техн. наук, доцент, Kurnosov Mikhail Georgievich - Candidate of Technical
кафедра «Вычислительные системы», Сибирский государст- Sciences, assistant professor, department «Computing system»,
венный университет телекоммуникаций и информатики, Siberian State University of Telecommunications and Infor-
науч. сотрудник, Лаборатория вычислительных систем, mation Sciences, researcher, Laboratory of Computer Systems,
Институт физики полупроводников им. А.В. Ржанова СО Rzhanov Institute of Semiconductor Physics of Siberian Branch
РАН, г. Новосибирск, Россия. E-mail: mkurnosov@sibguti.ru of Russian Academy of Sciences, Novosibirsk, Russia.
E-mail: mkurnosov@sibguti.ru
Выполнен экспериментальный анализ возможностей современных оптимизирующих компиляторов Intel C/C++ Compiler, GCC C/C++, LLVM/Clang и PGI C/C++ по автоматической векторизации циклов на архитектурах Intel 64 и Intel Xeon Phi. В качестве целевого набора тестовых циклов использован набор Extended Test Suite for Vectorizing Compilers. В ходе работы установлены ускорения для различных типов данных и определены классы циклов, автоматическая векторизация которых указанными компиляторами затруднена. Экспериментальная часть работы выполнена на двухпроцессорном NUMA -сервере (2 x Intel Xeon E5-2620v3, микроархитектура Intel Haswell) с сопроцессором Intel Xeon Phi 3120A.
Ключевые слова: векторизация; компиляторы; циклы; архитектура Intel 64; архитектура Intel Xeon Phi; векторные инструкции AVX.
The work deals with the experimental analysis of loop autovectorization facilities of modern optimizing compilers Intel C/C++ Compiler, GCC C/C++, LLVM/Clang and PGI C/C++ on Intel 64 and Intel Xeon Phi architectures. The Extended Test Suite for Vectorizing Compilers was used as a target test set of loops. During the work speedup for different data types was estimated and loop classes, for which autovectorization was impossible by the targeted compilers, were determined. The experimental part of the work was accomplished on the dual-processor NUMA server (2 x Intel Xeon E5-2620v3, Intel Haswell microarchitecture) with Intel Xeon Phi 3120A co-processor.
Keywords: vectorization; compilers; loops; Intel 64; Intel Xeon Phi; AVX vector extension.
Работа выполнена при поддержке РФФИ (проекты 16-07-00992, 15-07-00653).
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
Введение
Современные высокопроизводительные вычислительные системы (ВС) являются муль-тиархитектурными и реализуют несколько уровней параллелизма: параллелизм уровня вычислительных узлов (передача сообщений между процессами, process level parallelism - PLP), параллелизм уровня потоков (thread level parallelism -TLP), параллелизм уровня инструкций (instruction level parallelism - ILP), а также параллелизм обработки данных векторными арифметико-логическими устройствами (data level parallelism). Развитию векторных наборов инструкций (Intel AVX, IBM AltiVec, ARM NEON SIMD) уделяется значительное внимание со стороны разработчиков процессоров, в частности компания Fujitsu анонсировала переход в будущей версии эксафлопсной системы K Computer на процессоры с архитектурой ARMv8-A, реализующей широкие векторные регистры переменной длины (scalable vector extension), а компания Intel активно развивает набор инструкций AVX-512. По этой причине постановки задач и работы по (полу)автоматической векторизации программ компиляторами в последние десятилетия получили новый виток развития: компиляторная автовекторизация; SIMD-директивы OpenMP и Cilk Plus; языковые расширения Intel ISPC, Sierra; библиотеки C++17 SIMD Types, Boost.SIMD, gSIMD, Cyme.
Цель данной работы - выполнить экспериментальный анализ эффективности подсистем автоматической векторизации циклов в современных компиляторах Intel C/C++ Compiler, GCC C/C++, LLVM/Clang, PGI C/C++.
Учитывая отсутствие информации о реализуемых коммерческими компиляторами методах векторизации, анализ выполнен методом «черного ящика» - на тестовом наборе циклов из пакета Extended Test Suite for Vectorizing Compilers [1-4]. Определены классы типовых циклов, автоматическая векторизация которых указанными компиляторами затруднена, и произведён анализ таких циклов.
Наборы векторных инструкций
Наборы команд практически всех архитектур современных процессоров включают поддержку векторных инструкций: MMX/SSE/AVX в архитектурах IA-32 и Intel 64, набор AltiVec в архитектуре Power, NEON SIMD в семействе архитектур ARM, MSA в MIPS. Процессоры,
TECHNICAL SCIENCE. 2017. No 3
реализующие поддержку векторных инструкций, содержат одно или несколько параллельно работающих векторных арифметико-логических устройств (АЛУ) и совокупность векторных регистров. В отличие от векторных систем 1990-х гг., современные процессоры поддерживают выполнение операций с векторами относительно небольшой длины (64 - 512 бит), предварительно загруженными из оперативной памяти в векторные регистры (класс векторных систем «регистр - регистр»).
Основная сфера применения векторных инструкций - сокращение времени работы с одномерными массивами. Как правило, ускорение, достигаемое при использовании векторных инструкций, в первую очередь определяется количеством элементов массива, помещающихся в векторный регистр. Например, каждый из 16 векторных регистров AVX имеет ширину 256 бит, что позволяет загружать в них 16 элементов типа short int (16 бит), 8 элементов типа int или float (32 бита) и 4 элемента типа double (64 бита). Соответственно, при использовании AVX ожидаемое ускорение выполнения операций с массивами типа short int - 16 раз, int и float - 8 раз, double - 4 раза.
Процессоры Intel Xeon Phi поддерживают набор векторных инструкций AVX-512 и содержат 32 векторных регистра шириной 512 бит. Каждое ядро процессора c микроархитектурой Knights Corner содержит одно векторное АЛУ шириной 512 бит, а ядра процессора c микроархитектурой Knights Landing - два АЛУ.
Достижение максимального ускорения при векторной обработке требует учета микроархитектурных параметров процессоров. В числе важнейших - выравнивание на заданную границу начальных адресов массивов, загружаемых в векторные регистры (32 байта для AVX и 64 байта для AVX-512). Чтение и запись по адресам, не выравненным на заданную границу, выполняется медленнее. Снижение эффективности также может быть обусловлено смешанным использованием SSE- и AVX-инструкций. В этом случае при переходе от выполнения команд одного векторного расширения к другому процессор сохраняет (при переходе от AVX к SSE) или восстанавливает (в противоположном случае) старшие 128 бит векторных регистров YMM (AVX-SSE transition penaltie) [5].
При использовании векторных инструкций возможна ситуация, когда полученное ускорение будет превышать ожидаемое. Например, после
ISSN 0321-2653 ИЗВЕСТИЯ ВУЗОВ. СЕВЕРО-КАВКАЗСКИМ РЕГИОН._ТЕХНИЧЕСКИЕ НАУКИ. 2017. № 3
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION. TECHNICAL SCIENCE. 2017. No 3
векторизации цикла, в котором выполнялось поэлементное суммирование двух массивов, накладные расходы процессора на его выполнение уменьшаются за счет сокращения числа загрузок процессором инструкции сложения из памяти и ее декодирования; числа обращений к памяти за операндами операции сложения; количества вычислений условия завершения цикла (меньше обращений к модулю предсказания переходов процессора).
Кроме этого, причиной дополнительного ускорения может являться параллельное выполнение векторных инструкций несколькими векторными АЛУ. Таким образом, эффективно векторизованная версия программы в меньшей степени загружает ряд подсистем суперскалярного конвейера процессора. Последнее является причиной меньшего энергопотребления процессора при выполнении векторизованной программы по сравнению с ее скалярной версией [6].
Разработчикам прикладных программ доступны следующие способы использования векторных инструкций:
- ассемблерные вставки - полный контроль использования векторизации, наименее переносимый подход;
- интринсики (intrinsic) - набор типов данных и внутренних функций компилятора, напрямую отображающиеся на инструкции процессора (компилятор самостоятельно распределяет векторные регистры);
- SIMD-директивы компиляторов, стандартов OpenMP, OpenACC;
- языковые расширения Intel Array Notation, Intel ISPC, Apple Swift SIMD и библиотеки C++17 SIMD Types, Boost.SIMD, SIMD.js;
- автоматическая векторизация компилятором - простота использования, высокая переносимость кода.
В данной работе внимание уделено последнему подходу - автоматической векторизации компилятором. Такой способ векторизации не требует значительной модификации прикладных программ и обеспечивает их переносимость на уровне исходного кода между разными архитектурами процессоров.
Набор тестовых циклов
В качестве тестового набора в работе использован пакет Extended Test Suite for Vectorizing Compilers (ETSVC) [2], содержащий основные классы циклов, встречающихся в научных приложениях на языке C. Исходная вер-
сия пакета была разработана в конце 1980-х гг. группой Дж. Донгарры и содержала 122 цикла на языке Fortran для оценки эффективности компиляторов векторных ВС Cray, NEC, IBM, DEC, Fujitsu и Hitachi [3, 4]. В 2011 г. группа Д. Падуа транслировала пакет TSVC на язык программирования С и дополнила его новыми циклами [1]. Расширенная версия пакета содержит 151 цикл. Циклы разделены на категории: анализ зависимостей по данным (36 циклов), анализ потока управления и трансформация циклов (52 цикла), распознавание идиоматических конструкций (редукции, рекуррентности и т.п., 27 циклов), полнота понимания языка программирования (23 цикла). Кроме этого, в набор включены 13 контрольных циклов - тривиальные циклы, с векторизацией которых должен справиться каждый векторизующий компилятор.
Циклы оперируют с одномерными и двумерными глобальными массивами, начальные адреса которых выравнены на заданную границу (по умолчанию 16 байт). Одномерные массивы содержат 125-1024/sizeof(TYPE) элементов заданного типа TYPE, а двумерные - 256 элементов по каждому измерению.
Каждый цикл размещен в отдельной функции (см. листинг). Перед выполнением цикла в функции init (строка 5) выполняется инициализация массивов значениями, характерными для данного теста. Внешний цикл (строка 7) используется для увеличения времени выполнения теста (формирования статистики). Вызов пустой функции dummy (строка 10) предотвращает нежелательную оптимизацию внешнего цикла (трансформацию и вынесение внутреннего цикла за пределы внешнего, как инвариантного по отношению к внешнему).
Листинг. Пример цикла из тестового набора ETSVC / Listing. Example loop from the ETSVC benchmark
1 #define TY1E float
2 ¿define 111 (12: * 1024 / sizeof(TYPE)|
3 #define ntimes 100000
4 int sOOO'o {
5 I I" IKK) "I ;
6 clock t t = clock();
for (int ni = 0; Til < 2 * ntirnes; nl++) {
8 for (int 1 = 0; i < 111; i++)
9 X[i] = Y[i] + 1;
10 dummy({TYPE*)X, {TYPE*)Y, (TYPE*)Z, (TYPE*)U,
11 {TYPE*)V, aa, bb, cc, 0.0);
12 I
13 clock t end t = clock(); clock dif = end t — start t;
14 printf("S000\t %.2f \t\t",
15 (double){clock dif/1000000.0));
16 check(1); П return 0;
18 1
После выполнения циклов происходит вычисление и вывод на экран контрольной суммы элементов результирующего массива (функция check, строка 16).
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
Результаты экспериментов
Эксперименты проводились на двух системах. Первая система - сервер на базе двух процессоров Intel Xeon E5-2620 v4 (архитектура Intel 64, микроархитектура Broadwell, 8 ядер, Hyper-Threading включен, поддержка набора векторных инструкций AVX 2.0), 64 Гбайта оперативной памяти DDR4, операционная система GNU/Linux CentOS 7.3 x86-64 (ядро linux 3.10.0-514.2.2.el7). Вторая система - установленный в сервер сопроцессор Intel Xeon Phi 3120A (микроархитектура Knights Corner, 57 ядер, поддержка AVX-512), 6 Гбайт оперативной памяти, MPSS 3.8.
Анализировалась работа следующих компиляторов: Intel C/C++ Compiler 17.0; GCC C/C++ 6.3.0; LLVM/Clang 3.9.1; PGI C/C++ 16.10.
Компиляция векторизованной версии пакета ETSVC выполнялась с опциями, указанными в табл. 1 (столбец 2). Для генерации скалярной версии теста опции оптимизации сохранялись, но отключался векторизатор компилятора (столбец 3, табл. 1).
Таблица 1 / Table 1
Опции, используемые при компиляции / Compilers options
Компилятор Опции компиляции Отключение векторизатора
1 2 3
Intel C/C++ 17.0 -O3 -xHost -qopt-report3 -qopt-report-phase=vec,loop -qopt-report-embed -no-vec
GCC C/C++ 6.3.0 -O3 -ffast-math -fivopts -march=native -fopt-info-vec -fopt-info-vec-missed -fno-tree-vectorize -fno-tree-vectorize
LLVM/Clang 3.9.1 -O3 -ffast-math -fvectorize -Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize -fno-vectorize
PGI C/C++ 16.10 -O3 -Mvect -Minfo=loop,vect -Mneginfo=loop,vect -Mnovect
Глобальные массивы в пакете ETSVC были выравнены на границу 32 байта для процессора Intel Xeon и 64 байта - для Intel Xeon Phi. Эксперименты выполнены для массивов с элементами типов double, float, int и short.
Для данных типа double на архитектуре Intel 64 (процессор Intel Xeon Broadwell) были получены следующие результаты. Компилятор Intel C/C++ Compiler в общей сложности векторизовал 95 циклов, из них 7 смог векторизовать только он. Для GCC C/C++ общее количество векторизованных циклов составляет 79. При
TECHNICAL SCIENCE. 2017. No 3
этом не было ни одного такого цикла, который был бы векторизован только им. Компилятор PGI C/C++ векторизовал наибольшее количество циклов - 100, из них 13 векторизованы только этим компилятором. Наименьшее количество циклов было векторизовано LLVM/Clang - 52, 4 из которых смог векторизовать только он. Количество невекторизованных циклов ни одним из компиляторов составило 28.
Результаты векторизации для массивов с элементами типов float и int аналогичны double для всех компиляторов. Сопоставимые данные были получены и для типа short в случае использования Intel C/C++ Compiler, GCC C/C++ и LLVM/Clang. Исключение составляет PGI C/C++, который не векторизовал ни одного цикла, оперирующего данными этого типа.
На рис. 1 показаны результаты векторизации циклов компиляторами для типа данных double на архитектуре Intel 64. В ячейках таблицы указаны сокращенные обозначения результатов векторизации, которые были сформированы на основании анализа отчетов компиляторов о ходе векторизации для каждого из 151 цикла. В табл. 2 приведена расшифровка этих обозначений. Для других типов данных были получены аналогичные результаты.
В категории «Анализ зависимостей по данным» для типа данных double не были векторизованы ни одним из компиляторов 9 циклов. Проблемными в этой категории оказались циклы, содержащие линейные зависимости (рекуррентные отношения 1-го порядка), индуктивные переменные в сочетании с условными и безусловными (goto) переходами внутри цикла, вложенностью циклов и переменными значениями нижней и(или) верхней границы цикла и(или) шага выполнения итераций. В последнем случае на этапе статической компиляции ни один из компиляторов не может принять однозначного решения о наличии зависимости по данным и принимает пессимистическое решение о том, что зависимость существует.
В категории «Анализ потока управления и трансформация циклов» сложными для векторизации оказались 11 циклов, требующие выполнения следующих преобразований: расщепление тела цикла, перестановка циклов, расщепление вершин в графе зависимостей по данным (для устранения контура в графе и как следствие исключения выходных зависимостей и антизависимостей в цикле [7]) и растягивание массивов. Среди причин неудач компиляторов:
ISSN0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
TECHNICAL SCIENCE. 2017. No 3
зависимость значении переменных-счетчиков итераций вложенных циклов друг от друга; линейные зависимости в теле цикла (рекуррентные отношения 1-го порядка); условные и безусловные переходы в теле цикла.
Следующие идиоматические конструкции из категории «Распознавание идиоматических конструкций» оказались проблемными при векторизации 6 циклов: рекуррентные отношения
1-го и 2-го порядков, поиск элемента в массиве, свертка цикла и редукция с вызовом функции. Причина невекторизации циклов, содержащих рекуррентные отношения, заключается в наличии линейной зависимости по данным. В цикле, осуществлявшем поиск первого элемента в массиве, удовлетворяющего заданному условию, проблема возникла из-за прерывания вычислений в цикле безусловным переходом goto.
ICC V IF V IF V V D V V V V D KV M V D и V V с V V V ¥ D ¥ D □ ¥ и 3 D ¥ ¥ D ¥ V V V P¥ V FV К E IF ¥ ¥ PV FV D
PGI V IF V V V V D V V V □ V V V V SI D D V с V I' V ¥ Q с □ ¥ D D SI ¥ ¥ SI ¥ D D D D D s V D IF ¥ ¥ ¥ D D
LLVM V IF IF В ¥ 2- D 2- 2 IF R F; V V V HI CF CF V я IF IF V ¥ R ¥ ¥ CF CF V ¥ HI ¥ ¥ SI V R R R R V я я Я IF Я Я R D R
GCC и IF V V V ¥ H SO ¥ AP 0 It V V V MI S3 V V SP V V V ¥ lb ¥ FC И М м IF SI ¥ ¥ SI V n □ D D V p V IL IL H ¥ c- с
О О ™ £ H И H in S S ™ w £ fv fs w Si 3 1Л ¡Л S £г pi £ z sc S? ™ й ЛЦ S £ ^ s £ ?
И " " •A '/I •/1 " " " (л u -i -1 " i/i ■>! Ifl "
ICC PV FV EV V V ¥ D V ¥ V V D D D p V V V V V V FV V D V ¥ V V V V D ¥ ¥ V D V PV D V IF V V V IJT V V V ¥ D V
PGI D D D D V V V ¥ V V V V D □ V D V V V V D V 2Г D ¥ ¥ ¥ V ¥ V D ¥ ¥ ¥ D IF V V V TC V V V V V ¥ ¥ V ¥ ¥
LLVM V I' Г" V V V R ¥ V CF V R R OL R R CF CF CT CF я IF OV С CF CF F CF CF CF V R R D IF IF R V TC V V V я V V Я V R V
see 5 D V V V P3 V S3 V PS PS. A5> в? та 0 V V V V C- V V 5 H CF CF V V V ¥ V из V IF IT P V "C V V V CF V V 133 V V3 V
ГЛ -t 1 ■t -i _, -t iTi r- » fS ■Ji lh" г» « Ci ж ü -« -J — 14 ■w £ "7Г H <4 w кЛ r^ CO Pi "if
S» a a Si Si Si Si Si Si - s? 5 Si Si SI Si Si Si Si я 5 К s Й 3 я 5 я 31 irt 31 8 к
1« V V D D □ V M D и 3J V V V if V V H H к V V 1Г V V V V V Н! КГ V V V ¥ V V V V К V V V V V V ¥ V V V V V
PGI V ¥ V D D D V KE V V V V V V IF V V V V V V V V V V IF ¥ ¥ ГС Ж V V IF □ ¥ ¥ V V V IT V V V ¥ V ¥ V V V V V
LLVM я a. V Я P. R R ÜV CF CF CF IF V IF IF V V V T ¥ V CF sw CF V IF Я ¥ сг tn: IF IF IE IF IF IF IF V FC IF IF CF ¥ ¥ V ¥ V V V V V
GCC V IS V £■ D D ■js CS Si IB SS V V GS № V V V V V CF CF V fiO v V V С! CF S£ V v b V V V V V V v V У V V V v V
§ a 5 E Я ffi s 1 "t ГП ? in 1 У1 ¡7 3 Si Й a Д t a ■-■' -•r a Ä a 3t Я а гг. а i i ч 3 I ^ Is 3 3 s S 4 | > | 1 5 & i | ё ¥ t 3 5 "5 £
Рис. 1. Результаты векторизации циклов (архитектура Intel 64, тип данных double) / Fig. 1. Results of loops vectorization (Intel 64 architecture, double data type)
Таблица 2 / Table 2
Сокращенные обозначения результатов векторизации / Abbreviated notations of vectorization results
V Цикл векторизован полностью
PV Цикл векторизован частично (расщепление тела цикла с последующей векторизацией некоторых из полученных циклов)
RV Остаток цикла (remainder) не векторизован
IF Векторизация возможна, но не эффективна
D Зависимость по данным препятствует векторизации (предполагаемая линейная или нелинейная зависимость по данным в цикле)
M Сгенерировано несколько версий цикла, из которых в процессе выполнения программы будет выбрана невекторизованная (multiversioning)
BO Неподходящая операция или неподдерживаемая форма границы цикла (например, при использовании функций sinf и cosf)
AP Сложный шаблон доступа к элементам массива (например, величина шага по индексу больше 1)
R Значение, которое не может быть идентифицировано как результат редукции, используется вне цикла (наличие индуктивных переменных)
IL Переменная-счетчик внутреннего цикла не является инвариантом (например, переменная-счетчик внутреннего цикла зависит от переменной-счетчика внешнего цикла)
NI Невозможно вычислить количество итераций (нижняя и(или) верхняя граница цикла заданы аргументами функции)
CF Невозможно определить направление потока управления (условные переходы внутри цикла)
SS Цикл не подходит для векторной записи по несмежным адресам (scatter store, например, в случае упаковки двумерного массива в одномерный)
ME Цикл с несколькими выходами невозможно векторизовать (наличие break или exit внутри цикла)
FC Цикл содержит вызовы функций или данные, которые невозможно проанализировать
OL Значение не может быть использовано за пределами цикла (растягивание скаляров или использование одномерных и двумерных массивов в одном цикле)
UV Векторизатор не может понять поток управления в цикле (условные переходы внутри цикла)
SW Наличие оператора switch в цикле
US Неподдерживаемое использование в выражении (растягивание скаляров, распознавание охватывающих переменных)
GS В базовом блоке нет сгруппированных операций записи (развернутое скалярное произведение)
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
TECHNICAL SCIENCE. 2017. No 3
Над циклами, для которых была выполнена раскрутка (unrolling) вручную, компиляторы выполняют операцию свертки (rerolling) прежде, чем приступить к векторизации [8]. Исследуемые компиляторы приняли решение, что векторизация таких циклов возможна, но будет неэффективной. Причиной этого является использование косвенной адресации при обращении к элементам массива: X[Y[i]], где X - одномерный массив типа float; Y - указатель на целочисленный одномерный массив; i - переменная-счетчик итераций цикла.
Еще одна идиоматическая конструкция, вызвавшая проблемы с векторизацией - редукция, а именно нахождение суммы элементов одномерного массива. Здесь причиной невекторизации является наличие вызовов функции test, вычисляющей сумму 4-х элементов, начиная с того, который был ей передан в качестве аргумента. Компилятор Intel C/C++ Compiler сообщил в отчете о векторизации о том, что векторизация возможна, но не эффективна. Остальные исследуемые компиляторы указали вызов функции в качестве причины невозможности выполнения векторизации.
Категория «Полнота понимания языка программирования» содержит 2 невекторизованных ни одним из компиляторов цикла. Проблема обоих циклов - прерывание вычислений в цикле (вызов функции exit в первом случае и break во втором). Векторизаторы, реализованные в компиляторах, не смогли выполнить анализ потока управления.
сЗ 4500
0 4000 " 3500 я 3000
1 2500 g 2000 з 15 00 ш 1000
I 500
сР 0 m 0
LLVM/Clang
Рис. 2. Время выполнения теста (всех циклов) на процессоре Intel Xeon E5-2620 v4: внешние столбцы -невекторизованная версия теста; внутренние столбцы -векторизованная версия теста / Fig. 2. Execution time of the benchmark (all loops) on the Intel Xeon E5-2620 v4 CPU: outer columns - scalar version of the benchmark; inner columns - vectorized version of the benchmark
На рис. 2 показано суммарное время выполнения теста (всех циклов) для каждого типа данных и компилятора. На рис. 3 отражены медиана и максимальные значения ускорения
выполнения циклов после их векторизации компиляторами. Максимальное ускорение на архитектуре Intel 64 (процессор Intel Xeon Broadwell), полученное при векторизации компилятором Intel C/C++ Compiler, составило 6,96 для данных типа double, 13,89 для данных типа float, 12,39 для int и 25,21 для short. Для GCC C/C++ величина максимального ускорения равна 4,17, 158,02, 11,42 и 24,49 для типов double, float, int и short соответственно.
8 7
^ 6 «
* £■ g 5
« . g 4
g 3 s я
u 2
а 2 о
и 1
о 1
* 0
s я
а
о и
о >>
180 160 140 120 100 80 60 40 20 0
GCC
LLVM/Clang 158
126
PGI
68
ICC
1—1 fît
RFI 5 1-1 AR Л
Ü •о
ÛJ 4-1 4->
-Ч гя й Ч
Я О -гЧ О
3 -ч Л
О •+-< и
■с
J3 О -и о
b
Рис. 3. Ускорение выполнения векторизованных циклов на процессоре Intel Xeon E5-2620 v4: а - медиана ускорения
(учитывались только ускорения больше 1,15); b - максимальное ускорение / Fig. 3. Speedup for vectorized loops on the Intel Xeon E5-2620 v4 CPU: а - median value of speedup (only speedups above 1.15 were considered); b - maximum speedup
Компилятором LLVM/Clang получены следующие значения максимального ускорения: 5,21 (double), 126,2 (float), 4,55 (int) и 14,59 (short). А для PGI C/C++ эти значения составили 14,26, 23,22, 34,0 и 68,0 соответственно. Ускорение измерялось как отношение времени выполнения скалярного кода к времени выполнения векторизованного.
Как показал анализ, значения максимального ускорения для компиляторов Intel C/C++
а
ICC 4115
GCC 4 090
3 485
2 946
2 270
2 226
2 183
2 051
1 988
2 425
1 889
2 262
1 692
1 602
505
1 283
611
1445
1 400
137
1236
1148
1002
977
985
888
812
ISSN 0321-2653 ИЗВЕСТИЯ ВУЗОВ. СЕВЕРО-КАВКАЗСКИМ РЕГИОН._ТЕХНИЧЕСКИЕ НАУКИ. 2017. № 3
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION. TECHNICAL SCIENCE. 2017. No 3
Compiler, GCC C/C++ и LLVM/Clang соответствуют циклам, выполняющим операции редукции (сумма, произведение, поиск минимального или максимального элемента) над элементами одномерных массивов всех типов данных. Эти циклы относятся в ETSVC к категории «Распознавание идиоматических конструкций». Для компилятора PGI C/C++ максимальные ускорения для типов double и float были достигнуты для цикла, формирующего единичную матрицу (категория «Анализ потока управления и трансформация циклов»), а для int и short - в цикле из категории «Распознавание идиоматических конструкций», выполняющем операцию редукции (вычисление произведения).
Аномальные значения ускорения 126,2 и 158,02, полученные компиляторами GCC C/C++ и LLVM/Clang для типа float, объясняются эффективным распознаванием операций чтения или записи по несмежным адресам памяти [9] с использованием коэффициента чередования (interleaving factor), равного 2.
Однако полученное увеличение производительности не всегда является результатом векторизации. Для компилятора PGI C/C++ ускорение 68.0 для типа данных short объясняется тем, что в результате оптимизации вычисления в цикле не производились.
На архитектуре Intel Xeon Phi эксперименты проводились для компилятора Intel C/C++ Compiler 17.0. Вместо опции -xHost при компиляции использовалась -mmic. Результаты проведенных экспериментов для двух типов данных представлены на рис. 4.
Компилятору удалось векторизовать 99 циклов с данными типа double и 102 типа float. Основной причиной невекторизации циклов является предполагаемая зависимость по данным в вычислениях (28 циклов для типа
double и 27 для типа float). Частично векторизованы 12 циклов, оперирующих с массивами обоих типов. Аналогичные результаты были получены и для типов int и short. В этом случае максимальное ускорение для типа double составило 13,7, для типа float - 19,43, для int -30,84, а для short - 46,3. Для типов данных float и short максимальные значения ускорения были получены для циклов, выполняющих операции редукции над элементами одномерных массивов. Для типа double в цикле использовались функции sinf и cosf. В случае с типом int речь идет о контрольном цикле vbor, вычисляющем скалярное произведение шести одномерных массивов.
Заключение
Выполнен анализ эффективности подсистем автоматической векторизации циклов в современных компиляторах Intel C/C++ Compiler, GCC C/C++, LLVM/Clang, PGI C/C++ на архитектурах Intel 64 и Intel Xeon Phi. Установлено, что исследуемые компиляторы способны векторизовать от 39 до 77 % циклов от общего числа в пакете ETSVC. Наилучшие результаты показал Intel C/C++ Compiler, а наихудшие -LLVM/Clang.
Наиболее проблемными оказались циклы, содержащие условные и безусловные переходы, вызовы функций, индуктивные переменные, переменные в границах цикла и шаге выполнения итераций, а также такие идиоматические конструкции, как рекуррентности 1 -го или 2-го порядка, поиск первого подходящего элемента в массиве и свертка цикла.
В случаях, когда компиляторы не могут принять решение об эффективности или возможности векторизации цикла (например, при наличии в цикле нескольких переменных,
Рис. 4. Результаты векторизации (архитектура Intel Xeon Phi) / Fig. 4. Vectorization results (Intel Xeon Phi architecture)
ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.
которые могут ссылаться на одну и ту же область памяти), они генерируют скалярную и одну или несколько векторизованных версий цикла (многоверсионный код, multiversioning).
Решение о том, какая версия будет использоваться, принимается во время выполнения программы. Как показали результаты экспериментов, чаще всего в этом случае решение принимается в пользу скалярной версии цикла. Возможное решение - это аннотирование кода специальными директивами, указывающими на отсутствие зависимостей по данным, отсутствие множественных ссылок на одну область памяти.
Направление дальнейших работ - анализ и разработка методов эффективной векторизации установленного класса проблемных циклов, анализ возможностей применения JIT-компиляции [10] и оптимизации по результатам профилирования (profile-guided optimization).
Литература
1. Maleki S., Gao Ya. Garzarán M.J., Wong T., Padua D.A. An Evaluation of Vectorizing Compilers // Proc. of the International Conference on Parallel Architectures and Compilation Techniques (PACT'11). 2011. P. 372 - 382.
TECHNICAL SCIENCE. 2017. No 3
2. Extended Test Suite for Vectorizing Compilers URL: http://polaris.cs.uiuc.edu/~maleki1/TSVC.tar.gz (дата обращ ения 02.02.2017).
3. Callahan D., Dongarra J., Levine D. Vectorizing Compilers: A Test Suite and Results // Proc. of the ACM/IEEE conference on Supercomputing (Supercomputing'88). 1988. P. 98 - 105.
4. Levine D., Callahan D., Dongarra J. A Comparative Study of Automatic Vectorizing Compilers // Journal of Parallel Computing. 1991. Vol. 17. P. 1223 - 1244.
5. KonsorP. Avoiding AVX-SSE Transition Penalties // URL: https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties (дата обращения 02.02.2017).
6. Jibaja I., Jensen P., Hu N., Haghighat M., McCutchan J., Gohman D., Blackburn S., McKinley K. Vector Parallelism in JavaScript: Language and Compiler Support for SIMD // Proc. of the International Conference on Parallel Architecture and Compilation (PACT-2015). 2015. P. 407 - 418.
7. Векторизация программ: теория, методы, реализация. Сб. статей: Пер. с англ. и нем. М.: Мир. 1991. 275 с.
8. MetzgerR.C., Wen Zh. Automatic Algorithm Recognition and Replacement: A New Approach to Program Optimization. MIT Press. 2000. 219 p.
9. Nuzman D., Rosen I., Zaks A. Auto-vectorization of interleaved data for SIMD // Proc. of the 27th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '06). 2006. P. 132 - 143.
10. Rohou E., Williams K., Yuste D. Vectorization Technology To Improve Interpreter Performance // ACM Transactionson Architecture and Code Optimization. 2013. 9 (4). P. 26:1 - 26:22.
References
1. Maleki S., Gao Ya. Garzaran M.J., Wong T., Padua D.A. An Evaluation of Vectorizing Compilers // Proc. of the International Conference on Parallel Architectures and Compilation Techniques (PACT'11), 2011. pp. 372-382.
2. Extended Test Suite for Vectorizing Compilers Available at: http://polaris.cs.uiuc.edu/~maleki1/TSVC.tar.gz (accessed 02.02.2017).
3. Callahan D., Dongarra J., Levine D. Vectorizing Compilers: A Test Suite and Results // Proc. Of the ACM/IEEE conference on Supercomputing (Supercomputing'88), 1988. Pp. 98-105.
4. Levine D., Callahan D., Dongarra J. A Comparative Study of Automatic Vectorizing Compilers // Journal of Parallel Computing. 1991. Vol. 17. Pp. 1223-1244.
5. Konsor P. Avoiding AVX-SSE Transition Penalties. Available at: https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties (accessed date 02.02.2017).
6. Jibaja I., Jensen P., Hu N., Haghighat M., McCutchan J., Gohman D., Blackburn S., McKinley K. Vector Parallelism in JavaScript: Language and Compiler Support for SIMD // Proc. Of the International Conference on Parallel Architecture and Compilation (PACT-2015). 2015. Pp. 407-418.
7. Vektorizatsiya programm: teoriya, metody, realizatsiya. Sb. statei: Per. s angl. i nem. [Program Vectorization: Theory, Methods, Implementation. Coll. Works: Transl. from Eng. And Germ]. Moscow, Mir Publ., 1991, 275 p.
8. Metzger R.C., Wen Zh. Automatic Algorithm Recognition and Replacement: A New Approach to Program Optimization. MIT Press. 2000. 219 p.
9. Nuzman D., Rosen I., Zaks A. Auto-vectorization of interleaved data for SIMD // Proc. Of the 27th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '06). 2006. Pp. 132-143.
10. Rohou E., Williams K., Yuste D. Vectorization Technology To Improve Interpreter Performance // ACM Transactions on Architecture and Code Optimization. 2013. 9 (4). pp. 26:1-26:22.
Поступила в редакцию /Received 03 мая 2017 г. /May 03, 2017