30.6.1. ОСОБЕННОСТИ ПРОГРАММИРОВАНИЯ MULTIMEDIA UNIT
Константы
Операция загрузки вектора из памяти, или загрузка скаляра из обычного register file
является очень долгой, поэтому очень важно формировать основные константы на лету без
загрузки.
0
Основа формирования константы 0 - это векторный XOR одного операнда с самим собой.
Поскольку:
0 xor 0 = 0
и 1 xor 1 = 0
то после выполнения этой операции мы получим 0 в векторном регистре.
-1
Multimedia Unit имеет команды паралельного сравнения, которые устанавливают результатирующий
элемент вектора в 1...1, если условие выполняется, или в 0...0, если условие не выполняется.
Мы можем использовать вариант VCMPEQ - проверяющий на равенство используя в качестве
параметров один и тот же операнд два раза.
Поскольку X = X, то в результате весь векторный регистр будет содержать одни 11..11,
что означает -1 для каждого элемента вектора.
1
Получение единицы основано на простом соотношении:
1 = 0 - (-1)
а получать 0 и -1 мы уже умеем.
-X
Основа для получения -X:
-X = 0 - X
ноль мы тоже умеем получать.
NOT
_
Основа для получения X - операция XOR
Поскольку:
0 xor 1 = 1
1 xor 1 = 0
то получаем:
_
X = X xor (-1)
а -1 мы тоже умеем получать.
ABS
Для вычислений часто приходиться получать абсолютную величину числа (модуль).
Принцип вычисления модуля базируется на векторной операции VMAX - которая возвращает
максимальный из своих операндов.
Собственно:
|X| = X, если X >= 0
-X, если X < 0
или
|X| = MAX(X, -X)
собсвенно -X мы вычислять умеем: -X = 0 - X
NABS
То же самое действует для вычисления negative absolute value, только используется
не VMAX, а VMIN
-|X| = X, если X < 0
-X, если X >= 0
или
-|X| = MIN(X, -X)
собственно результат мы получили.
CMOV
Используя команды для паралельного сравнения и логику, очень легко достичь функциональности
Conditional Move, которая как известно уменьшает число ветвлений и тем самым увеличивает
быстродействие - что особенно необходимо для векторных вычислений.
Пример вычисляет:
destination[i] = (source1[i] > source2[i])? source1[i] : source2[i]
При этом считам что:
AF, C>G, D source2[i])? -1 : 0
Затем отрицательные результаты сравнения для первого операнда маскируются по маске
temp1[i] = source1[i] & mask[i]
а для второго операнда по инверсной маске
temp2[i] = source2[i] & (~mask[i])
что означает:
temp1[i] = (source1[i] > source2[i])? source1[i] : 0
и temp2[i] = (source1[i] > source2[i])? 0 : source[2]
делая
destination[i] = temp1[i] | temp2[i]
получаем то что мы и хотели:
destination[i] = (source1[i] > source2[i])? source1[i] : source2[i]
4 векторных команды и никаких ветвлений
Самое интересное, что таже техника используется и для FP векторов.
Поэтому есть команды типа Vector Parallel Compare и ЛОГИЧЕСКИЕ ВЕКТОРНЫЕ ОПЕРАЦИИ
для FP векторов, даже если FP вектор unit - является отдельным и не в состоянии
хранить integer data. Но возможность conditional move все искупает.
Bound
С помощью MAX и MIN можно делать насыщение по любым границам,
таким образом держа результаты в нужном диапазоне
Index Prev Next