Download presentation
Presentation is loading. Please wait.
1
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Оптимизирующий компилятор. Межпроцедурные оптимизации.
2
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Межпроцедурный анализ Как совместить хороший стиль программирования и требования к быстродействию приложения? Модульность. Читаемость кода и использование утилит для повторяющихся вычислений. Принцип реализации утилит как «черного ящика». Модульность исходного кода усложняет задачу по его оптимизации. Обсуждаемые в предыдущих разделах оптимизации – оптимизации процедурного уровня: эффективно работают только с локальными переменными всякий вызов функции - «черный ящик» неизвестны многие свойства переданных в процедуру параметров неизвестны свойства глобальных переменных Для решения этих проблем необходимо исследование программы в целом.
3
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Некоторые основные проблемы оптимизаций процедурного уровня 1.) Скалярные оптимизации: Reaches(b) = U для всех предшественников (defsout(p) U (reaches(p) ∩ ¬killed(p)) В случае вызова неизвестной функции в базовом блоке p, необходимо все глобалы и локалы, доступные функции, поместить в killed(p). Для качественных скалярных оптимизаций необходимы знания об свойствах функций, вызываемых внутри процедуры. 2.) Цикловые оптимизации: Для цикловых оптимизаций необходимы корректное определение объектов, которые могут ссылаться на одну память знание свойств функций внутри циклов (не изменяют итерационные переменные, не содержат выхода из программы и т.д.) оценка количества итераций цикла 3.) Векторизация: необходима информация о выравнивании объектов в памяти
4
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Протяжка константы через неизвестную функцию: Рассмотрим простую программку: test.c: extern void unknown(int *a); int main(){ int a,b,c; a=5; c=a; unknown(&a); if(a==5) printf("a==5\n"); b=a; printf("%d %d %d\n",a,b,c); return(1); } Сохраниться ли if утверждение в результирующем коде?
5
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Ассемблер полученный с помощью icl: icс –O2 test.c –S … call _unknown ;9.1 ; LOE ebx esi.B1.9: ; Preds.B1.8 add esp, 8 ;9.1 ; LOE ebx esi.B1.2: ; Preds.B1.9 mov edi, DWORD PTR [a.3.0.1] ;10.4 cmp edi, 5 ;10.7 jne.B1.4 ; Prob 0% ;10.7 ; LOE ebx esi edi … Вывод: В общем случае, когда о вызываемой функции ничего не известно, константа присвоенная переменной не протягивается через функцию, которая может изменить значение этой переменной.
6
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. CSE (Удаление общих подвыражений) #include extern void unknown(); float a,b; int main() { float c,d; scanf_s("%f",&a); scanf_s("%f",&b); c=0; if(sqrt(a+b)>3) c=a+b; else unknown(); d=sqrt(a+b)+c; printf("d=%f\n",d); return 1; } Здесь есть общее подвыражение sqrt(a+b). Будет ли CSE работать с этим подвыражением?
7
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. icl cse.c –S ….B1.3:: ; Preds.B1.2 movss xmm0, DWORD PTR [a] ;15.9 pxor xmm14, xmm14 ;14.1 addss xmm0, DWORD PTR [b] ;15.11 cvtps2pd xmm1, xmm0 ;15.11 sqrtsd xmm1, xmm1 ;15.4 comisd xmm1, QWORD PTR [_2il0floatpacket.0] ;15.14 jbe.B1.5 ; Prob 22% ;15.14 ; LOE rbx rbp rsi rdi r12 r13 r14 r15 xmm0 xmm1 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15.B1.4:: ; Preds.B1.3 movaps xmm14, xmm0 ;16.3 jmp.B1.7 ; Prob 100% ;16.3 ; LOE rbx rbp rsi rdi r12 r13 r14 r15 xmm1 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15.B1.5:: ; Preds.B1.3 call unknown ;19.3 ; LOE rbx rbp rsi rdi r12 r13 r14 r15 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15.B1.6:: ; Preds.B1.5 movss xmm0, DWORD PTR [a] ;21.8 addss xmm0, DWORD PTR [b] ;21.10 cvtps2pd xmm1, xmm0 ;21.10 sqrtsd xmm1, xmm1 ;21.3 …
8
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Однопроходная и двухпроходная компиляция Для того, чтобы собрать информацию о свойствах функций необходим дополнительный проход. Но поскольку, каждая функция в свою очередь может вызывать другие функции, а также себя (рекурсия), то необходимо произвести анализ графа вызовов (Call graph). Граф вызовов представляет взаимоотношение вызовов между процедурами в программе. Каждая вершина представляет процедуру и каждая грань (f,g) указывает, что процедура f вызывает процедуру g. Граф может быть статическим, вычисленным на этапе компиляции или динамическим, т.е. отражающим реальные вызовы при выполнении программы. (VTune) Одной из основных задач межпроцедурного анализа является построения графа вызовов и выяснения свойств функций на основе его анализа. (Например, глобальный анализ потоков данных требует знания о том, какие данные каждая функция модифицирует). Граф вызовов может быть полным и неполным. Если при сборе проекта используются библиотеки, свойства функций которых мы не знаем, то граф будет являться неполным и полноценный анализ не будет осуществлен.
9
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. FE (C++/C или Fortran) Внутреннее представление Профилировщик Скалярные оптимизации HPO Генератор кода Исходные файлы Обьектные файлы Временный файл или Obj с ВП IP/IPO оптимизации Скалярные оптимизации HPOГенератор кода Исполняемый файл Библиотека Архитектура компилятора
10
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Два вида межпроцедурных оптимизаций: модульная оптимизация для всей программы Qip[-] enable(DEFAULT)/disable single-file IP optimization within files /Qipo[n] enable multi-file IP optimization between files /Qipo-c generate a multi-file object file (ipo_out.obj) /Qipo-S generate a multi-file assembly file (ipo_out.asm) /Qipo-jobs specify the number of jobs to be executed simultaneously during the IPO link phase
11
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Изменится что-либо, если мы определим некую процедуру unknown и перекомпилируем с –ipo: #include extern float a,b; void unknown() { printf("a=%f b=%f\n",a,b); } icl –Qipo test.c unknown.c –Ob0 –Qipo-S Работают ли протыжка констант и удаление общих подвыражений?
12
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Анализ совмещений ( alias analysis) анализ совмещения через параметры анализ совмещения указателей для глобальных и статических указателей (Local point to analysis) Важная часть механизма определения зависимостей. В случае с анализом совмещения указателей с каждым указателем связывается множество возможных значений. Два указателя могут ссылаться на одну область памяти, если пересечение множеств их допустимых значений не пусто.
13
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Пример на LPT анализ #include int p1=1,p2=2; int *a,*b; void init(int **a, int **b) { *a=&p1; *b=&p1; // <= a and b poins to p1 } int main() { int i,ar[100]; init(&a,&b); printf("*a= %d *b=%d\n",*a,*b); for(i=0;i<100;i++) { ar[i]=i*(*a)*(*a); *b+=1; // *a is changed through *b } printf("ar[50]= %d p2=%d\n",ar[50],p2); } Можно ли осуществлять цикловые оптимизации с циклом for?
14
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Межпроцедурный анализ используется для протяжки атрибутов функций. Например, есть атрибуты no_side_effect, always_return и т.д. IPA используется для протяжки атрибутов переменных. Например, переменные помеченные атрибутом «адрес был взят» исключаются из многих оптимизаций. Этот атрибут для глобальных переменных устанавливает IPA. Продвижение данных (Data promotion). Каждая переменная имеет свою область видимости (scope). IPA позволяет протягивать данные, которые используются только в определенной процедуре, на уровень этой процедуры, что сразу позволяет включить их во многие оптимизации. Функции, используемые только в одной программе получают атрибут static. Удаление неиспользуемых глобальных переменных. Удаление мертвого кода. В данном случае, функция не будет включаться в исполняемый модуль, если она не входит в граф вызовов или все ее вызовы были подставлены (заинлайнены). (Вывод – для улучшения размеров кода и времени компиляции используйте аттрибут static). Протяжка информации о выравнивании аргументов. Если актуальные аргументы функции всегда выровнены, то мы можем улучшить векторизацию внутри процедуры.
15
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Межпроцедурные оптимизации используют связи, возникающие при вызовах процедур, для того, чтобы оптимизировать одну или несколько процедур или выяснить, как они соотносятся друг с другом. Протяжка константных аргументов если при каждом вызове процедуры f(i,j,k) в программе в качестве аргумента i всегда передается некая константа, то это позволяет присвоить первому формальному аргументу значение этой константы в коде процедуры f(). Протяжка возвращаемых значений. Если процедура всегда возвращает константное значение, то возможно протянуть это значение наружу. То же самое касается передаваемых в процедуру аргументов. Если перед выходом из процедуры значение аргумента константа, то ее также можно протянуть наружу.
16
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Пример. Константа протягивается в функцию через аргумент. Константа протягивается в вызывающую функцию. cat test.c #include extern void known(int variant,int *var); int main() { int var; int ttt; var=2; ttt=3; known(var,&ttt); printf("ttt=%i\n",ttt); } cat known.c void known(int var,int *ttt) { if(var>0) (*ttt)++; else (*ttt)--; } icc –Ob0 test.c known.c -fast -ipo-S … known: # parameter 1: %edi # parameter 2: %rsi..B2.1: # Preds..B2.0..___tag_value_known.8: #1.30 addl $1, (%rsi) #3.3 ret #6.1.align 16,0x90 … Таким образом, протянув константу удалось избавиться от ветвления.
17
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Подстановка (inlining). Подстановка удаляет накладные расходы связанные с подготовкой к вызову функции, удаляет переходы, которые могут быть источниками неэффективной работы памяти, позволяет эффективнее применять скалярные и цикловые оптимизации. Недостаток оптимизации – увеличение размера приложения. Как следствие – увеличение времени компиляции и необходимых для компиляции ресурсов. Евристики для подстановок пытаются выбрать наиболее выгодные для подстановки функции с тем, чтобы получить максимальный эффект для производительности не выходя за пределы допустимого увеличения кода. Аттрибут функции inline inline int exforsys(int x1) { return 5*x1; } Программист «рекомендует» компилятору сделать подстановку такой функции.
18
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Директивы для подстановки: Синтаксис: #pragma inline[recursive] #pragma forceinline[recursive] #pragma noinline Аргумент Recursive требует чтобы данная директива применялась ко всем вызовам, которые осуществляются данным вызовом. Директива inline рекомендует инлайнить noinline требует не инлайнить forceinline требует инлайнить Аналоги для языка Фортран cDEC$ ATTRIBUTES INLINE :: procedure cDEC$ ATTRIBUTES NOINLINE :: procedure cDEC$ ATTRIBUTES FORCEINLINE :: procedure 10/17/10
19
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. 10/17/10 Компиляторные опции подстановки: /Ob control inline expansion: n=0 disable inlining n=1 inline functions declared with __inline, and perform C++ inlining n=2 inline any function, at the compiler's discretion /Qinline-min-size: set size limit for inlining small routines /Qinline-min-size- no size limit for inlining small routines /Qinline-max-size: set size limit for inlining large routines /Qinline-max-size- no size limit for inlining large routines /Qinline-max-total-size: maximum increase in size for inline function expansion /Qinline-max-total-size- no size limit for inline function expansion
20
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. 10/17/10 /Qinline-max-per-routine: maximum number of inline instances in any function /Qinline-max-per-routine- no maximum number of inline instances in any function /Qinline-max-per-compile: maximum number of inline instances in the current compilation /Qinline-max-per-compile- no maximum number of inline instances in the current compilation /Qinline-factor: set inlining upper limits by n percentage /Qinline-factor- do not set set inlining upper limits /Qinline-forceinline treat inline routines as forceinline /Qinline-dllimport allow(DEFAULT)/disallow functions declared __declspec(dllimport) to be inlined /Qinline-calloc directs the compiler to inline calloc() calls as malloc()/memset()
21
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Клонирование функций Если в функцию f(x,y,x) передается x=2 в одном случае и x=3 в другом, то возможно заменить вызов функции f на вызовы f2 и f3. Частичная подстановка Если в функции f содержится вначале функции код, зависящий только от формальных аргументов, то этот код может быть подставлен в вызывающую функцию и удален из функции f.
22
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Девиртуализация для C++ Вызов функций через указатели дороже простого вызова. C++ - объектно-ориентированный язык поддерживающий высокий уровень абстракции. Возможность выполнения методов функции в зависимости от типа объекта времени выполнения. A => B => C Все наследуемые классы переопределяют virtual int foo() int process(class A *a) { return(a->foo()); }
23
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. #include class A { virtual int foo() { return 1; }; friend int process(class A *a); }; class B: public A { virtual int foo() { return 2; }; friend int process(class A *a); }; int process(class A *a) { return(a->foo()); }; void main() { A* pA = new A; B* pB = new B; int result1 = process(pA); int result2 = process(pB); printf("%d,%d\n",result1,result2); } icl -S rta0.cc Рассмотрим ассемблер для функции process: ?process@@YAHPAVA@@@ZPROC NEAR ; parameter 1: 4 + esp.B4.1: ; Preds.B4.0 mov ecx, DWORD PTR [4+esp] ;13.5 mov eax, DWORD PTR [ecx] ;14.9 call DWORD PTR [eax] ;14.9.B4.2: ; Preds.B4.1 ret ;14.9 ALIGN 16 ; LOE ; mark_end; ?process@@YAHPAVA@@@Z ENDP
24
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Трансформации данных. Перестановка полей структур. Если несколько полей используются в программе очень интенсивно, то разместив их рядом можно снизить количество промахов по памяти. Расщепление структуры (structure splitting) редко используемые поля выносятся в специальную «холодную» секцию. Без межпроцедурного анализа нельзя доказать возможность таких оптимизаций.
25
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Перестановка полей и разбиение структуры: struct.h : #ifndef PERF typedef struct { double x; char title[40]; double y; char title2[22]; double z; } VecR; #else typedef struct { char title[40]; char title2[22]; } ColdFields; typedef struct { double x; double y; double z; ColdFields *cold; } VecR; #endif
26
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. struct.c : #include #include "struct.h" int main() { int i, k; VecR *array; array=(VecR*)malloc(10000*sizeof(VecR)); #ifdef PERF for(i=0;i<10000;i++) array[i].cold=(ColdFields*)malloc(sizeof(ColdFields)); #endif for (i=0;i<10000;i++){ array[i].x = 1.0; array[i].y = 2.0; array[i].z = 0.0; } for(k=1;k<10000;k++) { for (i=k;i<9999;i++){ array[i].x = array[i-1].y+1.0; array[i].y = array[i+1].x+array[i+1].y; array[i].z = (array[i-1].y - array[i-1].x)/array[i-1].y; } } printf("%f \n",array[100].z); #ifdef PERF for(i=0;i<10000;i++) free(array[i].cold); #endif free(array); } icc struct.c -fast -o a.out icc struct.c -fast -DPERF -o b.out time./a.out real 0m0.808s time./b.out real 0m0.566s
27
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. Излишние ссылки на память (Pointer chasing) Доступ к данным через несколько ссылок – одна из самых распространенных проблем в С++ коде. Если структуры ваших данных не помещаются в подсистеме памяти, то при разименовании каждой ссылки вы рискуете ожидать данные из памяти. 10/17/10 Class Employers { Personal_info *p; … };; Class personal_info { Family_info *f; … }; Class family_info { int members; … }; All_members+= employer->p->f->members;
28
Software & Services Group, Developer Products Division Copyright© 2010, Intel Corporation. All rights reserved. *Other brands and names are the property of their respective owners. 10/17/10 Спасибо за внимание!
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.