GCC векторных расширений предлагают хороший, достаточно портативный способ доступа к некоторым инструкциям SIMD на разных аппаратных архитектурах, не прибегая к аппаратным характеристикам (или автоматической векторизации).
Реальным вариантом использования является вычисление простой аддитивной контрольной суммы.Единственное, что неясно, это как безопасно загружать данные в вектор.
typedef char v16qi __attribute__ ((vector_size(16)));
static uint8_t checksum(uint8_t *buf, size_t size)
{
assert(size%16 == 0);
uint8_t sum = 0;
vec16qi vec = {0};
for (size_t i=0; i<(size/16); i++)
{
// XXX: Yuck! Is there a better way?
vec += *((v16qi*) buf+i*16);
}
// Sum up the vector
sum = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5] + vec[6] + vec[7] + vec[8] + vec[9] + vec[10] + vec[11] + vec[12] + vec[13] + vec[14] + vec[15];
return sum;
}
Кажется, что приведение указателя к типу вектора работает, но я боюсь, что это может ужасно взорватьсяесли SIMD ожидает, что векторные типы будут правильно выровнены.
Единственный другой вариант, о котором я подумал, - это использовать временный вектор и явно загружать значения (с помощью memcpy или поэлементного присваивания), нопри тестировании это противодействовало большей части ускорения, полученного с использованием SIMD-инструкций.В идеале я бы предположил, что это будет что-то вроде общей __builtin_load()
функции, но, похоже, ее не существует.
Какой более безопасный способ загрузки данных в вектор с риском выравнивания?