Загрузка данных для векторных расширений GCC

Векторные расширения 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 () , но, похоже, ее не существует.

Какой более безопасный способ загрузки данных в вектор может вызвать проблемы с выравниванием?

8
задан Jonathan Leffler 17 February 2012 в 00:20
поделиться