Библиотека сайта rus-linux.net
Внутренние функции компилятора GCC для обработки данных в векторной форме
Авторы: George Koharchik, Kathy Jones, Перевод: А.Панин
Это продолжение статьи. Начало смотри здесь.
Типы векторов, компилятор и отладчик
Для того, чтобы использовать аппаратное обеспечение для работы с векторами, необходимо сообщить компилятору об использовании внутренних функций для генерации SIMD-кода, подключить заголовочный файл, задающий типы векторов и использовать векторный тип для преобразования ваших данных в векторную форму.
Примеры параметров командной строки для использования SIMD-инструкций приведены в таблице 1. (Эта статья описывает только те параметры, что приведены в таблице, а GCC позволяет использовать гораздо большее их количество.)
Процессор | Параметры |
X86/MMX/SSE1/SSE2 | -mfpmath=sse -mmmx -msse -msse2 |
ARM Neon | -mfpu=neon -mfloat-abi=softfp |
Freescale Altivec | -maltivec -mabi=altivec |
- arm_neon.h - ARM Neon (типы данных и прототипы внутренних функций)
- altivec.h - Freescale Altivec (типы данных и прототипы внутренних функций)
- mmintrin.h - X86 MMX
- xmmintrin.h - X86 SSE1
- emmintrin.h - X86 SSE2
X86: MMX, SSE, SSE2 типы данных и отладка
- MMX: __m64 64 бита для хранения целочисленных значений, разделенные на восемь 8-битных целочисленных значений, четыре 16-битных значения или два 32-битных значения.
- SSE1: __m128 128 бит для хранения четырех чисел с плавающей точкой одинарной точности.
- SSE2: __m128i 128 бит для хранения упакованных целых чисел любого размера, __m128d 128 бит для хранения двух чисел с плавающей точкой двойной точности.
__m64 avariable; /* хранит 4 значения типа short */
print (short[]) avariable
print/d acharvector
Эта команда позволяет вывести значение переменной acharvector в виде серии значений в десятичной системе счисления.
PowerPC Altivec: типы данных и отладка
- vector unsigned char: вектор из 16 беззнаковых однобайтных значений
- vector signed char: вектор из 16 знаковых однобайтных значений
- vector bool char: вектор из 16 беззнаковых однобайтных значений, трактующихся как логические (0 false, 255 true)
- vector unsigned short: вектор из 8 беззнаковых двухбайтных значений
- vector unsigned short: вектор из 8 беззнаковых двухбайтных значений
- vector bool short: вектор из 8 беззнаковых двухбайтных значений, трактующихся как логические (0 false, 65535 true)
- vector unsigned int: вектор из 4 беззнаковых четырехбайтных значений
- vector signed int: вектор из 4 знаковых четырехбайтных значений
- vector bool int: вектор из 4 беззнаковых четырехбайтных значений, трактующихся как логические (0 false, 2^32-1 true)
- vector float: вектор из 4 значений с плавающей точкой
Отладчик выводит эти векторы в виде наборов значений отдельных элементов.
ARM Neon: типы данных и отладка
- uint64x1_t - одно 64-битное беззнаковое целочисленное значение
- uint32x2_t - два 32-битных беззнаковых целочисленных значения
- uint16x4_t - четыре 16-битных беззнаковых целочисленных значения
- uint8x8_t - восемь 8-битных беззнаковых целочисленных значений
- int32x2_t - два 32-битных знаковых целочисленных значения
- int16x4_t - четыре 16-битных знаковых целочисленных значения
- int8x8_t - восемь 8-битных знаковых целочисленных значений
- int64x1_t - одно 64-битное знаковое целочисленное значение
- float32x2_t - два 32-битных значения с плавающей точкой
- uint32x4_t - четыре 32-битных беззнаковых целочисленных значения
- uint16x8_t - восемь 16-битных беззнаковых целчисленных значений
- uint8x16_t - шестнадцать 8-битных беззнаковых целочисленных значений
- int32x4_t - четыре 32-битных знаковых целочисленных значения
- int16x8_t - восемь 16-битных знаковых целочисленных значений
- int8x16_t - шестнадцать 8-битных знаковых целочисленных значений
- uint64x2_t - два 64-битных беззнаковых целочисленных значения
- int64x2_t - два 64-битных знаковых целочисленныхзначения
- float32x4_t - четыре 32-битных значения с плавающей точкой
- uint32x4_t - четыре 32-битных беззнаковых целочисленных значения
- uint16x8_t - восемь 16-битных беззнаковых целочисленных значений
Отладчик выводит эти векторы как наборы отдельных элементов.
В директории samples/simple вы найдете ряд примеров использования этих типов данных.
Теперь, когда мы рассмотрели типы данных векторов, давайте поговорим о разработке программ для работы с векторами.
Как отмечает Ian Ollman, программы для работы с векторами тесно связаны с множественным перемещением данных (для описания используется термин "blitter"). Они загружают данные в память, обрабатывают их и затем сохраняют в другой области памяти. Перемещение данных между областями памяти и регистрами векторов является необходимостью, но при этом представляет собой дополнительную работу. Перемещение больших фрагментов данных из памяти, их обработка и запись назад в память позволяет минимизировать эту работу.
float anarray[4] __attribute__((aligned(16))) = { 1.2, 3.5, 1.7, 2.8 };
Невозможность выравнивания данных может привести к получению верного результата, получению неверного результата без сообщения об ошибке или краху приложения. Существуют техники для работы с невыровненными данными, но они приводят к снижению производительности по сравнению с обработкой выровненных данных. Вы можете найти примеры в архиве с исходными кодами.
В коде примеров использованы внутренние функции компилятора для X86, Altivec и Neon. Эти функции используют политику наименований для удобства расшифровки их назначения. Подробнее об этой политике наименований:
Внутренние функции Altivec используют префикс "vec_". Перегрузка функций в стиле C++ позволяет им принимать аргументы различных типов.
Внутренние функции Neon используют названия в соответствии с шаблоном [операция][флаги]_[тип]. Флаг "q" обозначает, что функция работает с векторами из четырех значений общей длиной в 128 бит ("quad word").
суффикс s число с плавающей точкой одинарной точности d число с плавающей точкой двойной точности i128 знаковое 128-битное целое число i64 знаковое 64-битное целое число u64 беззнаковое 64-битное целое число i32 знаковое 32-битное целое число u32 беззнаковое 32-битное целое число i16 знаковое 16-битное целое число u16 беззнаковое 16-битное целое число i8 знаковое 8-битное целое число u8 беззнаковое 8-битное целое число pi# 64-битный вектор из упакованных #-битных целых чисел pu# 64- битный вектор из упакованных #-битных беззнаковых целых чисел epi# 128- битный вектор из упакованных #-битных беззнаковых целых чисел epu# 128- битный вектор из упакованных #-битных беззнаковых целых чисел ps 128- битный вектор из упакованных чисел с плавющей точкой одинарной точности ss 128-битный вектор из одного числа с плавающей точкой одинарной точности pd 128-битный вектор из чисел с плавающей точкой двойной точности sd 128-битный вектор из одного числа с плавающей точкой (128-битного) двойной точности si64 64-битный вектор из одного 64-битного целого числа si128 128-битный вектор
В таблице 2 приведены внутренние функции, использованные в коде примеров.
Операция | Altivec | Neon | MMX/SSE/SSE2 |
Загрузка данных из памяти в вектор | vec_ld | vld1q_f32 | _mm_set_epi16 |
vec_splat | vld1q_s16 | _mm_set1_epi16 | |
vec_splat_s16 | vsetq_lane_f32 | _mm_set1_pi16 | |
vec_splat_s32 | vld1_u8 | _mm_set_pi16 | |
vec_splat_s8 | vdupq_lane_s16 | _mm_load_ps | |
vec_splat_u16 | vdupq_n_s16 | _mm_set1_ps | |
vec_splat_u32 | vmovq_n_f32 | _mm_loadh_pi | |
vec_splat_u8 | vset_lane_u8 | _mm_loadl_pi | |
Перемещение данных из вектора в память | vec_st | vst1_u8 | |
vst1q_s16 | _mm_store_ps | ||
vst1q_f32 | |||
vst1_s16 | |||
Сложение векторов | vec_madd | vaddq_s16 | _mm_add_epi16 |
vec_mladd | vaddq_f32 | _mm_add_pi16 | |
vec_adds | vmlaq_n_f32 | _mm_add_ps | |
Вычитание векторов | vec_sub | vsubq_s16 | |
Умножение векторов | vec_madd | vmulq_n_s16 | _mm_mullo_epi16 |
vec_mladd | vmulq_s16 | _mm_mullo_pi16 | |
vmulq_f32 | _mm_mul_ps | ||
vmlaq_n_f32 | |||
Арифметический сдвиг | vec_sra | vshrq_n_s16 | _mm_srai_epi16 |
vec_srl | _mm_srai_pi16 | ||
vec_sr | |||
Байтовые перестановки | vec_perm | vtbl1_u8 | _mm_shuffle_pi16 |
vec_sel | vtbx1_u8 | _mm_shuffle_ps | |
vec_mergeh | vget_high_s16 | ||
vec_mergel | vget_low_s16 | ||
vdupq_lane_s16 | |||
vdupq_n_s16 | |||
vmovq_n_f32 | |||
vbsl_u8 | |||
Конвертация типов данных | vec_cts | vmovl_u8 | _mm_packs_pu16 |
vec_unpackh | vreinterpretq_s16_u16 | ||
vec_unpackl | vcvtq_u32_f32 | ||
vec_cts | vqmovn_s32 | _mm_cvtps_pi16 | |
vec_ctu | vqmovun_s16 | _mm_packus_epi16 | |
vqmovn_u16 | |||
vcvtq_f32_s32 | |||
vmovl_s16 | |||
vmovq_n_f32 | |||
Комбинирование векторов | vec_pack | vcombine_u16 | |
vec_packsu | vcombine_u8 | ||
vcombine_s16 | |||
Максимальное значение | _mm_max_ps | ||
Минимальное значение | _mm_min_ps | ||
Логические операции над векторами и | _mm_andnot_ps | ||
_mm_and_ps | |||
_mm_or_ps | |||
Округление значений | vec_trunc | ||
Разное | _mm_empty |
Это продолжение статьи. Вернуться к началу. Перейти к следующей части.