7 707
订阅者
-424 小时
-177 天
-6430 天
帖子存档
7 707
Аппаратные решения, упрощающие программную конвейеризацию
- «Вращающиеся регистры» — часть регистрового файла отводится на область вращающихся регистров. Инструкции, использующие некоторый архитектурный регистр из этой области будут обращаться к различным физическим регистрам по мере исполнения итераций. Через какое-то количество итераций, вновь произойдет обращение к исходному физическому регистру. Это позволяет работать с различными итерациями цикла одновременно, и при этом не требуется явных пересылок между регистрами.
- Предикаты и предикатное исполнение инструкций, при котором предикатом работает некоторые специальные предикаты цикла. Эти предикаты позволяют включать и отключать некоторые инструкции цикла в процессе прохождения итераций, тем самым реализуя пролог и эпилог цикла в основном его коде, а также упрощают раскрытие условных операций в теле цикла.
- Аппаратная поддержка циклов, при которой программа дает процессору информацию о размере цикла и о параметрах индексной переменной. Это позволяет сократить накладные расходы на организацию цикла. Также позволяет настроить скорость вращения и размер группы вращающихся регистров.
7 707
Способы реализации предвыборки кода
1. Предварительная загрузка:
Способ заключается в том, чтобы загружать в память блоки данных, которые скорее всего понадобятся в будущем. Загруженные данные могут сохраняться в кеше для более быстрого доступа к ним в дальнейшем.
2. Спекулятивная предвыборка:
Способ заключается в том, чтобы загрузить в память данных, которые могут понадобиться в будущем на основе анализа предыдущих запросов. Например, если вы последовательно обрабатываете элементы списка, то спекулятивная предвыборка может загрузить следующий элемент в память на всякий случай.
3. Предвыборка на основе предсказаний:
Способ заключается в том, чтобы загрузить данные, которые вероятно будут запрошены в будущем, на основе анализа предыдущих запросов и статистических данных.
4. Асинхронная предвыборка:
Способ заключается в том, чтобы асинхронно загружать данные в фоновом режиме.
7 707
Предвыборка кода
В компьютерной архитектуре, предвыборкой кода называют технологию, используемую в микропроцессоре для увеличения скорости исполнения программ, уменьшая время, в течение которого процессор находится в состоянии ожидания из-за отсутствия инструкций для исполнения.
Современные микропроцессоры гораздо быстрее чем память, вследствие чего инструкции исполняемой программы не могут считывыться достаточно быстро, чтобы обеспечить непрерывность работы процессора. Добавление кэша может обеспечить более быстрый доступ к необходимым инструкциям.
Другими словами, предвыборка кода - выдача запросов со стороны процессора в оперативную память для считывания инструкций заблаговременно, до того момента, как эти инструкции потребуется исполнять. В результате этих запросов, инструкции загружаются из памяти в кэш. Когда инструкции потребуется исполнять, доступ к ним будет осуществляться значительно быстрее, так как задержка при обращении в кэш на порядки меньше, чем при обращении в оперативную память.
7 707
Векторизация (параллельные вычисления)
Векторизация — вид распараллеливания программы, при котором однопоточные приложения, выполняющие одну операцию в каждый момент времени, модифицируются для выполнения нескольких однотипных операций одновременно.
Скалярные операции, обрабатывающие по паре операндов заменяются на операции над массивами, обрабатывающие несколько элементов вектора в каждый момент времени.
Пример:
Показан фрагмент программы, который поэлементно перемножает два массива, состоящие из чисел:
for (i = 0; i < 1024; i++)
C[i] = A[i] * B[i];
Данный цикл может быть векторизован так:
for (i = 0; i < 1024; i+=4)
C[i:i+3] = A[i:i+3] * B[i:i+3];
Запись C[i:i+3] означает вектор из 4 элементов — от C[i] до C[i+3] включительно, а под * понимается операция поэлементного умножения векторов.7 707
Перестановка циклов
Перестановка циклов — оптимизация компилятора при которой меняется порядок итерационных переменных, относящихся к группе вложенных циклов. Итерационная переменная, используемая во внутреннем цикле, перемещается во внешний цикл, и наоборот. Это часто делается, чтобы гарантировать, что элементы многомерных массивов доступны в том порядке, в котором они хранятся в памяти, т.е. для улучшения локальности ссылок.
Например, следующий код:
for (int j=0; j<10; j++) {
for (int i=0; i<20; i++)
y[i][j] = i + j;
}
в результате применения оптимизации может быть преобразован в:
for (int i=0; i<20; i++) {
for (int j=0; j<10; j++)
y[i][j] = i + j;
}
В отдельных случаях, такое преобразование может создать контекст для дальнейших оптимизаций.7 707
Распространение констант
Распространение констант — оптимизация, заменяющее выражение, которое при выполнении всегда возвращает одну и ту же константу, самой этой константой. Это может быть константа, определённая ранее, или встроенная функция, применённая к константам.
Рассмотрим следующий пример:
int x = 14;
int y = 7 - x / 2;
return y * (28 / x + 2);
Распространение x возвращает:
int x = 14;
int y = 7 - 14 / 2;
return y * (28 / 14 + 2);
Далее, свёртка констант и распространение y возвращают следующее:
int x = 14;
int y = 0;
return 0;7 707
Свёртка констант
Свёртка констант — оптимизация, вычисляющая константные выражения на этапе компиляции. Прежде всего, упрощаются константные выражения, содержащие числовые литералы(фиксированное значение). Также могут быть упрощены выражения, содержащие никогда не изменяемые переменные или переменные, объявленные как константы.
Рассмотрим пример:
i = 320 * 200 * 32;Компилятор, поддерживающий свёртку констант, не будет генерировать две инструкции умножения и запись полученного результата. Вместо этого он распознает эту конструкцию как константное выражение и заменит её на вычисленное значение (в данном случае
2 048 000).7 707
Принцип оптимизации удаления общих подвыражений
Применение оптимизации основано на анализе доступных выражений.
Выражение x + y является доступным в некоторой точке p программы, если:
- вдоль любого пути от начального узла к p выражение x + y вычисляется до достижения точки p;
- между вычислениями выражений и достижением точки p нет изменения значений переменных x и y.
Эффективность преобразования главным образом определяется тем, что суммарное время записи и нескольких чтений новой переменной оказывается меньше, чем суммарное время, затрачиваемое на вычисление старого выражения каждый раз, когда оно встречается в коде.
На практике на итоговую эффективность влияет также ряд других факторов, в частности распределение переменных по регистрам.
7 707
Удаление общих подвыражений
Удаление общих подвыражений — это оптимизация компилятора (преобразование), которое уничтожает повторные вычисления общих подвыражений и заменяет их на использование сохраненного после первого вычисления значения.
Рассмотрим следующий фрагмент кода:
a = b * c + g; d = b * c * d;К нему применимо следующее преобразование:
tmp = b * c; a = tmp + g; d = tmp * d;которое окажется эффективным, если суммарное время записи и нескольких чтений новой переменной "tmp" окажется меньше, чем суммарное время, затрачиваемое на вычисление выражения "
b * c" каждый раз, когда оно встречается в коде.7 707
Слияние циклов
Слияние циклов — оптимизация компилятора, выполняющая объединение нескольких циклов, смежных в дереве циклов, в один. Преобразование возможно, если циклы имеют одинаковое количество итераций и не зависят друг от друга по данным. Слияние циклов может повысить локальность данных, что повышает эффективность работы кэша.
Например, код:
int i, a[100], b[100];
for (i = 0; i < 100; i++) {
a[i] = 1;
}
for (i = 0; i < 100; i++) {
b[i] = 2;
}
эквивалентен:
int i, a[100], b[100];
for (i = 0; i < 100; i++) {
a[i] = 1;
b[i] = 2;
}7 707
Расщепление тела цикла
Расщепление тела цикла или Loop fission — оптимизация компилятора, которая разбивает цикл в программе на несколько циклов, каждый из которых имеет те же индексные границы, однако содержит только часть тела исходного цикла.
Например, следующий код:
int i, a[100], b[100];
for (i = 0; i < 100; i++) {
a[i] = 1;
b[i] = 2;
}
в результате применения оптимизации преобразовывается в:
int i, a[100], b[100];
for (i = 0; i < 100; i++) {
a[i] = 1;
}
for (i = 0; i < 100; i++) {
b[i] = 2;
}
На некоторых архитектурах может оказаться более выгодным исполнить два цикла вместо одного объединённого, так как, например, локальность данных в таком случае может оказаться выше.7 707
Оптимизация циклов
Оптимизация циклов - это один из методов внутрипроцедурной оптимизации.
Основные методы оптимизации циклов:
- Раскрытие цикла - вместо выполнения цикла используются отдельные инструкции, которые применяются к нескольким элементам данных сразу. Это уменьшает количество итераций цикла и увеличивает производительность выполнения.
- Использование константной оптимизации - константные значения выносятся за пределы цикла, чтобы они не вычислялись каждый раз во время выполнения цикла.
- Обратный цикл - цикл выполняется в обратном порядке. Это может уменьшить количество пропусков кэша и увеличить локальность ссылок на данные.
- Предварительный выход из цикла - проверка условия выхода из цикла применяется на каждой итерации цикла в начале итерации, вместо того чтобы проверять его в конце итерации.
7 707
Принципы оптимизации, применяемые в различных методах оптимизации в компиляторах
1. Уменьшение избыточности- повторное использование результатов вычислений, сокращение числа перевычислений;
2. Компактификация кода - удаление ненужных вычислений и промежуточных значений;
3. Сокращение числа переходов в коде. Например, использование встраивания функций или размотки цикла позволяет во многих случаях ускорить выполнение программы ценой увеличения размера кода;
4. Локальность - код и данные, доступ к которым необходим в ближайшее время, должны быть размещены рядом друг с другом в памяти, чтобы следовать принципу локальности ссылок;
5. Использование иерархии памяти - размещать наиболее часто используемые данные в регистрах общего назначения, менее используемые — в кэш, ещё менее используемые — в оперативную память, наименее используемые — размещать на диске.
6. Распараллеливание - изменение порядка операций может позволить выполнить несколько вычислений параллельно, что ускоряет исполнение программы.
7 707
Локальная оптимизация
Локальная оптимизация - это метод оптимизации, который применяется к небольшим фрагментам кода, называемым базовыми блоками, для улучшения его производительности. Она применяется в компиляторах на этапе генерации машинного кода для оптимизации программы.
Примеры локальных оптимизаций включают в себя следующие:
- Устранение идентичных операций;
- Устранение избыточных вычислений;
- Замена сложных операций более простыми (например, замена умножения на степень двойки на сдвиг);
- Замена медленных операций более быстрыми;
- Ускорение циклов;
- Встраивание функций;
- Устранение ненужных промежуточных вычислений и т.д.
Такая оптимизация позволяет сократить количество инструкций, необходимых для выполнения программы, что уменьшает время ее работы и повышает производительность.
7 707
Peephole-оптимизация
Метод оптимизации программного кода, который заключается в анализе нескольких последовательных инструкций в программе (называемых "peephole"), чтобы определить, можно ли их заменить более эффективной комбинацией или порядком инструкций.
Для проведения peephole-оптимизации на уровне ассемблера, компилятор анализирует последовательность операций и заменяет их на более оптимизированные.
Например, удвоение числа может быть более эффективно выполнено с использованием левого сдвига или путём сложения числа с таким же.
7 707
Что такое peephole?
Peephole - это небольшой набор последовательных машинных инструкций, который обычно составляется для исправления архитектурных особенностей процессора или определенного набора инструкций.
Peephole может использоваться для оптимизации кода, например, замена нескольких инструкций на эквивалентную одну для сокращения времени выполнения программы.
Также, peephole может использоваться для обработки ошибок в коде, например, если происходит переполнение стека, то в peephole можно добавить инструкцию для очистки стека или добавление проверки на условия, при которых может произойти переполнение.
7 707
Первый в России ускоренный онлайн-бакалавриат «Фронтенд и мобильная разработка» — от Яндекс Практикума и университета ИТМО.
— Учёба 2,5 года вместо четырёх лет
— Диплом государственного образца по направлению «Прикладная информатика»
— Можно выбрать специализацию: фронтенд, iOS- или Android-разработка
— Удобно совмещать с работой: обучение онлайн, 20-25 часов в неделю
— Преподаватели — действующие разработчики
— Стажировка в крупных IT-компаниях
— Системное развитие хард-и софтскилов
Программы рассчитаны на людей со средним профессиональным или высшим образованием.
Обучение почти в два раза короче, потому что формат позволяет перезачесть часть общих предметов и оставить только профильные.
Поступайте, чтобы стать востребованным разработчиком и подготовиться к роли тимлида.
→ Оставить заявку
Реклама АНО ДПО "Образовательные технологии Яндекса", ИНН:7704282033, erid: LjN8KCpNz
7 707
Для чего нужен оптимизирующий компилятор?
Оптимизирующий компилятор - это компилятор, который способен преобразовывать входной код программы с целью повышения её эффективности и оптимизации. Это достигается за счет применения различных алгоритмов оптимизации, которые преобразуют и оптимизируют код для улучшения его производительности.
Могут выполнять различные виды оптимизаций:
1. Устранение неиспользуемого кода.
2. Избавление от повторяющегося кода.
3. Векторизация - преобразование циклов с пересылкой данных между массивами в код, работающий с векторами.
4. Улучшение работы с памятью.
5. Избавление от избыточных вычислений.
6. Использование регистров и кэша процессора.
7 707
Межпроцедурная оптимизация
Межпроцедурная оптимизация - это вид оптимизации в программировании, который позволяет улучшить производительность программы, включая несколько функций и подпрограмм. Она основана на анализе потоков данных и контроля за использованием памяти, и как следствие, на основании этого, устранении избыточных действий.
Применение межпроцедурной оптимизации может ускорить выполнение программы, снизить потребление памяти, а также сократить объем программы за счет удаления неиспользуемого кода или упрощения сложных алгоритмов.
Кроме того, межпроцедурная оптимизация может применяться для устранения повторяющихся действий, таких как перезапись переменных, вызов одной и той же функции с разными аргументами и др.
7 707
Индуктивная переменная
Индуктивная переменная — переменная в циклах, последовательные значения которой образуют арифметическую прогрессию. Наиболее распространенный пример — счётчик цикла. Индуктивные переменные часто используются в индексных выражениях массивов.
Например, в следующем примере, i и j являются индуктивными переменными:
for ( i = 0; i < 10; i++ ) {
j = 17 * i;
}
Традиционные методы оптимизации предусматривают распознавание индуктивных переменных и удаление их из цикла.