1 / 38

Оптимизирующий компилятор. Векторизация.

Оптимизирующий компилятор. Векторизация. Тенденция в развитии микропроцессоров:. Параллельное выполнение инструкций. Последовательное выполнение инструкций. Конвейеризация Суперскалярность Векторные операции Многоядерные и многопроцесорные решения

nailah
Download Presentation

Оптимизирующий компилятор. Векторизация.

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Оптимизирующий компилятор.Векторизация.

  2. Тенденция в развитии микропроцессоров: Параллельное выполнение инструкций Последовательное выполнение инструкций • Конвейеризация • Суперскалярность • Векторные операции • Многоядерные и многопроцесорные решения Оптимизирующий компилятор – инструмент, транслирующий исходный код программы в исполняемый модуль и оптимизирующий исходный код для получения лучшей производительности.Параллелизация – трансформация последовательно выполняющейся программы в программу, в которой наборы инструкций выполняются одновременно и сохраняется «смысл» программы.

  3. Одна из технологий параллелизации программы – векторизация циклов. C[1] = A[1]+B[1] C[2] = A[2]+B[2] C[3] = A[3]+B[3] C[4] = A[4]+B[4] Векторизация A[1] A[2] A[3] A[4] B[1] B[2] B[3] B[4] B[1] A[1] + B[2] A[2] B[3] A[3] B[4] A[4] = C[1] C[2] C[3] C[4] C[1] C[2] C[3] C[4]

  4. Типичная векторная инструкцияпредставляет собой операцию над двумя векторами в памяти или в регистрах фиксированной длины. Данные векторные регистры могут быть загружены из памяти за одну операцию или по частям. • Векторизация - это компиляторная оптимизация, которая заменяет скалярный код на векторный. Т.е. эта оптимизация «упаковывает» данные в вектора и заменяет скалярные операции на операции с векторами (пакетами). • A(1:n:k) – секция массива в Фортране. • for(i=0;i<U,i++) { for(i=0;i<U;i+=vl) { • S1: lhs1[i] = rhs1[i]; S1: lhs1[i:i+vl-1:1] = rhs1[i:i+vl-1:1]; • … => … • Sn: lhsn[i] = rhsn[i]; Sn: lhsn[i:i+vl-1:1] = rhsn[i:i+vl+1:1]; • } }

  5. MMX,SSEВекторные инструкции и векторизация Первоначально была предложена технология MMX. MMX (Multimedia Extensions) – набор инструкций, выполняющиххарактерныедляпроцессовкодирования/декодированияпотоковыхаудио/видеоданныхдействия. MMM0-MMM7 64 битные регистры для работы с целыми числами концепция пакетов, каждый из этих регистров мог хранить 2 – 32 битных целых числа 4 - 16 битных 8 - 8 битных 47 инструкций, которые деляться на несколько груп: перемещение данных арифметические сравнения конвертации логические распаковки сдвига пустые инструкции получения состояния

  6. SSE(Streaming SIMD Extensions, потоковое SIMD-расширение процессора) — набор инструкций позволяющий работать с множеством данных – SIMD(Single Instruction, Multiple Data, Одна инструкция — множество данных). SSE включает в себя : 8128-битных регистров(xmm0 до xmm7) набор инструкций, который производит операции со скалярными и упакованными типами данных. Технология EMM64T добавляла к этому набору еще 8 128 битных регистра (xmm8 до xmm15). SSE2,SSE3,SSEE3,SSE4 – последующие расширения этой идеи. SSE2 добавил тип упакованных данных с плавающей точкой двойной точности. AVX новое расширение системы команд (Advanced vector extensions) AVX предоставляет различные улучшения, новые инструкции и новую схему кодирования машинных кодов. Размер векторных регистров SIMD увеличивается с 128 до 256 бит. Регистры YMM0-YMM15 Существующие 128-битные инструкции используют младшую половину YMM регистров.

  7. Данные различных типов могут быть упакованы в векторные регистры следующим образом: Выбор подходящего для вычислений типа данных может существенно сказаться на производительности приложения.

  8. Optimization with SwitchesSIMD – SSE, SSE2, SSE3, SSE4.2 Support 2x doubles 4x floats SSE4.2 SSE3 SSE2 1x dqword 16x bytes SSE 8x words MMX* 4x dwords 2x qwords * MMX actually used the x87 Floating Point Registers - SSE, SSE2, and SSE3 use the new SSE registers

  9. Группы иструкций: • Инструкции перемещения данных: (data movement instructions) : • Instruction Suffix Description • movdqa перемещение выравненного двойного четверного слова (double quadword) • movdqu перемещение невыравненного двойного четверного слова • mova [ ps, pd ] перемещение выравненого вещественного • movu [ ps, pd ] перемещение невыравненного вещественного • movhl [ ps ] перемещение верхней части упакованного вещественного вниз • movlh [ ps ] перемещение нижней части упакованного вещественного вверх • movh [ ps, pd ] перемещение верхней части упакованного вещественного • movl [ ps, pd ] перемещение нижней части упакованного вещественного • mov [ d, q, ss, sd ] перемещение скалярных данных • lddqu перемещение невыравненного двойного четверного слова • mov<d/sh/sl>dup перемещение и дублирование • pextr [ w ] извлечение слова • pinstr [ w ] вставка слова • pmovmsk [ b ] перемещение маски • movmsk [ ps, pd ] перемещение маски • Инструкции для перемещения выравненных (aligned) данных не могут использоваться для работы с адресами памяти не выравнеными на 16.

  10. Целочисленные арифметические инструкции : • Instruction Suffix Description • padd [ b, w, d, q ] векторное сложение (знаковые и беззнаковые) • psub [ b, w, d, q ] векторное вычитание (знаковые и беззнаковые) • padds [ b, w ] векторное сложениес насыщением (знаковые) • paddus [ b, w ] векторное сложениес насыщением (беззнаковые) • psubs [ b, w ] векторное вычитание с насыщением (знаковые) • psubus [ b, w ] векторное вычитание с насыщением (беззнаковые) • pmins [ w ] векторный минимум (знаковые) • pminu [ b ] векторный минимум (беззнаковый) • pmaxs [ w ] векторный максимум (знаковый) • pmaxu [ b ] векторный максимум (беззнаковый)

  11. Арифметические операции с вещественными числами : • Instruction Suffix Description • add [ ss, ps, sd, pd ] сложение • div [ ss, ps, sd, pd ] деление • min [ ss, ps, sd, pd ] минимум • max [ ss, ps, sd, pd ] максимум • mul [ ss, ps, sd, pd ] умножение • sqrt [ ss, ps, sd, pd ] квадратный корень • sub [ ss, ps, sd, pd ] вычитание • rcp [ ss, ps] приблизительноеобратное • rsqrt [ ss, ps] приблизительный обратный квадратный корень • Идиоматические арифметические инструкции : • Instruction Suffix Description • pang [ b, w ] векторное среднее с округлением (беззнаковые) • pmulh/pmulhu/pmull [ w ] векторное умножение • psad [ bw ] векторная сумма абсолютных разниц (беззнаковые) • pmadd [ wd ] векторное умножение и сложение (знаковые) • addsub [ ps, pd ] вещественное сложение/вычитание • hadd [ ps, pd ] вещественное горизонтальное сложение • hsub [ ps, pd ] вещественное горизонтальное вычитание

  12. Логические инструкции : • Instruction Suffix Description • pand побитовый логический AND • pandn побитовый логический AND-NOT • por побитовый логический OR • pxor побитовый логический XOR • and [ ps, pd ] побитовый логический AND • andn [ ps, pd ] побитовый логический AND-NOT • or [ ps, pd ] побитовый логический OR • xor [ ps, pd ] побитовый логический XOR • Инструкции сравнения : • Instruction Suffix Description • pcmp<cc> [ b, w, d ] векторное сравнение • cmp<cc> [ ss, ps, sd, pd ] вещественное сравнение • Здесь <cc> обозначает операцию сравнения. • lt – меньше, gt – больше, eq - равно

  13. Конвертирующие инструкции : • Instruction Suffix Description • packss [wb, dw] упаковывать с насыщением(знаковые) • paсkus [wb] упаковывать с насыщением (беззнаковые) • cvt<s2d> конвертация • cvtt<s2d> конвертация с усечением • Инструкции сдвига : • Instruction Suffix Description • psll [ w, d, q, dq ] логический сдвиг влево • psra [w, d] арифметический сдвиг вправо • psrl [ w, d, q, dq ] правый логический сдвиг • Перестановочные (shuffle) инструкции : • Instruction Suffix Description • pshuf [ w, d ] векторная перестановка • pshufh [w] векторная перестановка верхней части • pshufl [w] векторная перестановка нижней части • ырга [ ps, pd ] перестановка

  14. Расспаковывающие инструкции : • Instruction Suffix Description • punpckh [bw, wd, dq, qdq] распаковать верхнюю часть • punpckl [bw, wd, dq, qdq] распаковать нижнюю часть • unpckh [ps, pd] распаковать верхнюю часть • unpckl [ps, pd] распаковать нижнюю часть • Инструкции работы с кэшем : • Instruction Suffix Description • movnt [ ps, pd, q, dq ] перемещать выравненные не временные данные • prefetch<hint> подрузить в кэш • Управляющие состоянием инструкции • Обычно используются опреционной системой.

  15. Три набора опций для использования процессорно-специфических расширений • Опции –x<EXT> например –xSSE4_1 • Проводит проверку процессора • Ошибка времени выполнения в случае запуска программы на прцессоре отличном от указанного в опции • Опции –m<EXT> например –mSSE3 • Нет проверки • Падение программы при выполнении специфической процессорной инструкции в случае запуска на процессоре не поддерживающем указанное расширение • Опции –ax<EXT> например –axSSE4_2 • Автоматический выбор оптимального варианта – наличие кода для разных векторных расширений • Проверка процессора доступна только для Интеловских процессоров • Для не Интеловского прцессора используется умолчательный код • Умолчательная опция –mSSE2

  16. Типичная векторная инструкцияпредставляет собой операцию над двумя векторами в памяти или в регистрах фиксированной длины. Данные векторные регистры могут быть загружены из памяти за одну операцию или по частям. • Описание основ SSE технологии можно прочитать в CHAPTER 10PROGRAMMING WITHSTREAMING SIMD EXTENSIONS (SSE)документа«Intel 64 and IA-32 Intel Architecture Software Developer's Manual»(Volume 1) • Microsoft Visual Studio поддерживает набор SSE интринсиков, которые позволяют напрямую использовать SSE инструкции из С/C++ кода. Это позволяет осуществлять векторизацию вручную. Для этого необходимо подключить xmmintrin.h, который определяет тип __m128 (это векторный тип) и операции с ним. • Допустим мы хотим векторизовать вручную цикл: • for(i=0;i<N;i++) • C[i]=A[i]*B[i]; • Для этого необходимо : • организовать/заполнить векторные переменные • запустить интринсик для умножения векторных переменных • скопировать результаты вычислений в память • (Для экпериментов использовался Intel компилятор версии 12.0) (Использовать icl –help для получения опций компилятора. )

  17. #include <stdio.h> #include <xmmintrin.h> #define N 40 int main() { float a[N][N][N],b[N][N][N],c[N][N][N]; int i,j,k,rep; __m128 *xa,*xb,*xc; for(i=0;i<N;i++) for(j=0;j<N;j++) for(k=0;k<N;k++) { a[i][j][k]=1.0; b[i][j][k]=2.0;} for(rep=0;rep<10000;rep++) { #ifdef PERF for(i=0;i<N;i++) for(j=0;j<N;j++) for(k=0;k<N;k+=4) { xa=(__m128*)&(a[i][j][k]); xb=(__m128*)&(b[i][j][k]); xc=(__m128*)&(c[i][j][k]); *xc=_mm_mul_ps(*xa,*xb); } #else for(i=0;i<N;i++) for(j=0;j<N;j++) for(k=0;k<N;k++) c[i][j][k]=a[i][j][k]*b[i][j][k]; #endif } printf("%f\n ",c[21][11][18]); } Пример, иллюстрирующий векторизацию с помощью SSE интринсиков. icl -Od test.c -Fetest1.exe icl -Od test.c -DPERF -Fetest_opt.exe time test1.exe 2.000000 CPU time for command: 'test1.exe' real 3.406 sec user 3.391 sec system 0.000 sec time test_opt.exe 2.000000 CPU time for command: 'test_opt.exe' real 1.281 sec user 1.250 sec system 0.000 sec

  18. Полученный прирост производительности - 2.7x. • Для работы некоторых векторных инструкций необходимо, чтобы адреса в памяти были выравнены на 16. В нашем тесте это получилось случайно, в реальном случае нужно об этом заботиться. • Тест оптимизированный компилятором показывает следующий результат: • icl test.c -Qvec_report3 -Fetest_intel_opt.exe • time test_intel_opt.exe • 2.000000 • CPU time for command: 'test_intel_opt.exe' • real 0.328 sec • user 0.313 sec • system 0.000 sec

  19. Допустимость векторизации • Векторизация – перестановочная оптимизация. Операции меняют порядок выполнения. • Перестановочные оптимизации допустимы, если не изменяется порядок зависимостей. • Таким образом мы получили критерий допустимости векторизации в терминах зависимостей. • Простейший вариант – зависимостей в векторизуемом цикле нет. • Зависимости в векторизуемом цикле есть, но их порядок после векторизации совпадает с порядком в невекторизованном цикле.

  20. /Qvec-report[n] • control amount of vectorizer diagnostic information • n=0 no diagnostic information • n=1 indicate vectorized loops (DEFAULT) • n=2 indicate vectorized/non-vectorized loops • n=3 indicate vectorized/non-vectorized loops and prohibiting • data dependence information • n=4 indicate non-vectorized loops • n=5 indicate non-vectorized loops and prohibiting data • dependence information • Использование: icl -c -Qvec_report3 loop.c • Примеры диагностики: • C:\loops\loop1.c(5) (col. 1): remark: LOOP WAS VECTORIZED. • C:\loops\loop3.c(5) (col. 1): remark: loop was not vectorized: vectorization possible but seems inefficient. • C:\loops\loop6.c(5) (col. 1): remark: loop was not vectorized: nonstandard loop is not a vectorization candidate.

  21. Фортран акктивно используется в описании векторизации, поскольку имеет удобное понятие секции массива. • В упрощенном виде: • DO I=1,N • A(I)=… • END DO • при векторизации переводится в • DO I=1,N/K • A(I:I+K)=… • END DO • где K – число элементов матрицы A размещаемых в векторном регистре. • Наглядным критерием возможности векторизации является то факт, что введение секций массива не порождает зависимостей. • DO I=1,N DO I=1,N/K • A(I)=A(I)+C => A(I:I+K) = A(I:I+K)+C • END DO END DO • Может быть векторизован. • DO I=1,N DO I=1,N/K • A(I+1)=A(I)+C => A(I+1:I+1+K)=A(I:I+K)+C • END DO END DO • Не может быть векторизован.

  22. Предположение: Цикл можно векторизовать, если дистанция для зависимости >= K, где K – количество элементов массива, входящих в векторный регистр. Проверяем утверждение с помощью компилятора: ifort test.F90 -o a.out –vec_report3 echo ------------------------------------- ifort test.F90 -DPERF -o b.out –vec_report3 ./build.sh test.F90(11): (col. 1) remark: loop was not vectorized: existence of vector dependence. ------------------------------------- test.F90(11): (col. 1) remark: LOOP WAS VECTORIZED. PROGRAM TEST_VEC INTEGER,PARAMETER :: N=1000 #ifdef PERF INTEGER,PARAMETER :: P=4 #else INTEGER,PARAMETER :: P=3 #endif INTEGER A(N) DO I=1,N-P A(I+P)=A(I) END DO PRINT *,A(50) END

  23. Факторы, влияющие на производительность векторизованного кода. Рассмотрим такой тест: INTEGER :: A(1000),B(1000) INTEGER I,K INTEGER, PARAMETER :: REP = 500000 A = 2 DO K=1,REP CALL ADD(A,B) END DO PRINT *,SHIFT,B(101) CONTAINS SUBROUTINE ADD(A,B) INTEGER A(1000),B(1000) INTEGER I !DEC$ UNROLL(0) DO I=1,1000-SHIFT B(I) = A(I+SHIFT)+1 END DO END SUBROUTINE END

  24. ifort test1.F90 -O2 -Ob0 /fpp /DSHIFT=0 -Fea.exe -Qvec_report >a.out 2>&1 ifort test1.F90 -O2 -Ob0 /fpp /DSHIFT=1 -Feb.exe -Qvec_report >b.out 2>&1 %TIME% a.exe %TIME% b.exe Скомпилируем исходный тест, передав в программу разные значения переменной SHIFT. Получим: C:\users\aanufrie\students\continuous2>C:\u4win\bin\x86_win32\time.exe a.exe 0 3 CPU time for command: 'a.exe' real 0.125 sec user 0.094 sec system 0.000 sec C:\users\aanufrie\students\continuous2>C:\u4win\bin\x86_win32\time.exe b.exe 1 3 CPU time for command: 'b.exe' real 0.297 sec user 0.281 sec system 0.000 sec

  25. ifort test1.F90 -O2 -Ob0 /fpp /DSHIFT=0 /Fas -Ob0 -Qvec_report3 -S –Fatest0.s ifort test1.F90 -O2 -Ob0 /fpp /DSHIFT=1 /Fas -Ob0 -S -Qvec-report3 –Fatest1.s Для данного цикла имеем для быстрого случая: .B2.5: ; Preds .B2.5 .B2.4 $LN83: ;;; B(I) = A(I+SHIFT)+1 movdqa xmm1, XMMWORD PTR [eax+ecx*4] ;17.11 $LN84: paddd xmm1, xmm0 ;17.4 $LN85: movdqa XMMWORD PTR [edx+ecx*4], xmm1 ;17.4 $LN86: add ecx, 4 ;16.3 $LN87: cmp ecx, 1000 ;16.3 $LN88: jb .B2.5 ; Prob 99% ;16.3

  26. Для данного цикла имеем для медленного случая: • .B2.5: ; Preds .B2.5 .B2.4 • $LN81: • ;;; B(I) = A(I+SHIFT)+1 • movdqu xmm1, XMMWORD PTR [4+eax+ecx*4] ;17.11 • $LN82: • paddd xmm1, xmm0 ;17.4 • $LN83: • movdqa XMMWORD PTR [edx+ecx*4], xmm1 ;17.4 • $LN84: • add ecx, 4 ;16.3 • $LN85: • cmp ecx, 996 ;16.3 • $LN86: • jb .B2.5 ; Prob 99% ;16.3 • MOVDQA—Move Aligned Double Quadword • MOVDQU—Move Unaligned Double Quadword

  27. Производительность векторизованного цикла зависит от того, каким образом векторизуемые объекты расположены в памяти. Поэтому первый аспект имеющий огромное значение для производительности программы –выравнивание данных в памяти. • Выравнивание структур данных (Data Structure Alignment) это метод с помощью которого данные располагаются и доступаются в компьютерной памяти. Это понятие заключает в себе два различных, но взаимосвязанных вопроса: выравнивание данных (Data alignment) и заполнение структур данных (Data structure padding). • Выравнивание данных определяет, как те или иные данные расположены относительно границ памяти. Этот факт как правило связан с типом данных. • Заполнение структур данных подразумевает вставку безымянных полей в структуру данных, для того чтобы сохранить относительное выравнивание полей структуры.

  28. Информация о выравнивании может быть получена с помощью интринсика __alignof__. Размер переменной данного типа и выравнивание по умолчанию может зависеть от типа компилятора. • printf("int: sizeof=%d align=%d\n",sizeof(a),__alignof__(a)); • Выравнивание для 32 битного Интеловского C++ компилятора: • bool sizeof = 1 alignof = 1 • wchar_t sizeof = 2 alignof = 2 • short int sizeof = 2 alignof = 2 • int sizeof = 4 alignof = 4 • long int sizeof = 4 alignof = 4 • long long int sizeof = 8 alignof = 8 • float sizeof = 4 alignof = 4 • double sizeof = 8 alignof = 8 • long double sizeof = 8 alignof = 8 • void* sizeof = 4 alignof = 4 • Те же самые правила используются и при выравнивании массивов. • Существует возможность выравнять объект необходимым образом: • __declspec(align(16)) float x[N];

  29. structfoo{ bool a;  char pad1[1];   short b;   char pad2[4];   long long c; bool d;  char pad3[7]; };                      • struct foo {    • bool a; • short b;   •  long long c; •   bool d; • }; Порядок полей в структуре оказывает влияние на размер объекта производного типа. С целью уменьшения размера объекта рекомендуется размещать поля в объекте в порядке уменьшения их размера.Можно использовать __declspec для выравнивания полей структуры. typedef struct aStuct{ __declspec(align(16)) float x[N]; __declspec(align(16)) float y[N]; __declspec(align(16)) float z[N]; };

  30. Производительность векторизованного цикла зависит от того как обрабатываются векторные регистры, поэтому в общем случае скалярный цикл, работающий с одним массивом DO I=K,N A(I)=… END DO векторизуется следующим образом: if(! N<K) { t1=N-K+1; /* общее кол-во итераций */ t2=&A[K]&15; if(t2!=0) { /* проверяем выравнен ли объект в памяти */ t2=(16-t2)/SIZEOF(array_element); } if(t1<4+t2) { /* нечего векторизовать */ t3=0; goto TAIL; } t3=t1-((t1-t2)&3)); /* кол-во векторизованных итераций */ DO I=1,t2 /* головной цикл */ A[I+K-1]=… END DO DO I=t2+1,t3,4 /* векторизованный цикл */ A[I+K-1:I+K+3]=… END DO TAIL: DO I=t3+1,t1/* хвостовой скалярный цикл */ A[I+K-1]=… END DO }

  31. Каким образом правильное выравнивание может помочь в случае скалярного цикла, обрабатывающего несколько массивов? void Calculate(float * restrict a,float * restrict b,float * restrict c ,int n) { int i; for(i=0;i<n;i++) { a[i] = ((a[i]*a[i])+(b[i]*b[i]))/(c[i]*c[i]); } return; } icl -S vec7.c -Qstd=c99 -QxSSE4.2 -O3 Легко найти векторизованный цикл и убедиться, что используются векторные инструкции для доступа к невыравненной памяти. .B1.20:: ; Preds .B1.18 .B1.20 movss xmm2, DWORD PTR [rcx+r9*4] ;1.6 movss xmm0, DWORD PTR [rdx+r9*4] ;1.6 ... В компиляторе есть возможность предупредить компилятор о том, что переданные в функцию аргументы будут выравнены: __assume_aligned(a,16);

  32. Добавив в нашу функцию следующие строки __assume_aligned(a,16); __assume_aligned(b,16); __assume_aligned(c,16); мы получим код без головного выравнивающего цикла, использующий инструкции movaps для доступа к памяти. Оценим выгодность полученного кода добавив к нашей функции функцию main следующего вида: #include <stdio.h> #define N 1000 extern void Calculate(float *x,float *y,float *z,int n); int main() { __declspec(align(16)) float x[N]; __declspec(align(16)) float y[N]; __declspec(align(16)) float z[N]; int i,rep; for(i=0;i<N;i++) { x[i] = 1;y[i] = 1; z[i] = 1; } for(rep=0;rep<10000000;rep++) { Calculate(&x[0],&y[0],&z[0],N);} printf("x[0]=%f\n",x[0]); } Icl main.c vec8.c -Qstd=c99 -QxSSE4.2 -O3 -Fevec8 => 5.43s icl main.c vec7.c -Qstd=c99 -QxSSE4.2 -O3 –Fevec7 => 5.57s

  33. Векторизация может ухудшить производительность маленьких циклов. INTEGER I,J,A(100) INTEGER,VOLATILE :: K,N K=1 N=11 DO J=1,1000000 DO I=K,N A(I)=J END DO END DO PRINT *,A(55) END Без векторизации тест выполняется 0.10s а с векторизацией 0.13s. Почему так происходит? Цикл в примере разложится на 3 части: от 2 до 5 – скалярный цикл (3 итерации) от 5 до 8 – векторизированный цикл (1 итерация) от 9 до 11 – скалярный цикл (3 итерации)

  34. Векторизация в общем случае может быть выполнена не только на внутреннем цикле. Если мы имеем вложенное множество циклов и внутренний цикл не может быть векторизован из-за существования каких-либо зависимостей, то можно пытаться векторизовать внешний цикл: DO I=1,N DO J=1,K A(J,I) =.. END DO END DO Векторизация DO I=1,N DO J=1,K A(J,I:I+P-1)=… END DO END DO Будет ли полезной такая оптимизация?

  35. Векторизация и многоверсионный код. Дополнительная возможность для улучшения производительности – формирование многоверсионного кода, т.е. кода включающего проверки времени выполнения. Примеры случаев, когда это может работать: void sub(int *a,int *b) { int i; for(i=0;i<1000;i++) a[i]=b[i]; } void sub(int *a,int n) { int i; for(i=0;i<1000;i++) a[i]=a[i+n]; } Можно проверить работает ли многоверсионная векторизация для gcc или интеловского компилятора.

  36. Существуют полезные прагмы, которые вы можете использовать для улучшения эффективности векторизации: __declspec(align(n)) – указывает компилятору выравнивать переменную на n-байтовую границу #pragma ivdep Предлагает игнорировать предполагаемую векторную зависимость #pragmavector{aligned|unaligned|always} Определяет как векторизивать цикл #pragma novector Цикл не должен быть векторизован Аналоги для Фортрана !DEC$ IVDEP !DEC$ VECTOR ALWAYS !DEC$ NOVECTOR

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

  38. Спасибо за внимание!

More Related