SIMD-инструкции загрузка в регистры

Пытаюсь понять, хотя бы на самом примитивном уровне, как работать с SIMD. Нашел вот такую статью: https://woboq.com/blog/utf-8-processing-using-simd.html

Там простой код и пояснение, но я не могу понять:

int fromUtf8(const char *src, int len, unsigned short *dst) 
{

//Мы будем обрабатывать ввод по 16 байт за раз, поэтому длина должна быть не менее 16.

    while(len >= 16) 
    {
 
    //Загрузить 128 бит в векторный регистр. Мы используем встроенный 'loadu', где «u» означает не выровненный. Загрузка выровненных данных намного быстрее, но здесь мы не знаем, выровнен ли источник.

        __m128i chunk = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src));
 

//Определить, является ли это ASCII, проверив, установлен ли старший бит одного байта:

        if (!_mm_movemask_epi8(chunk)) 
        {
              //....
        }

}

В этом коде я не могу понять - авто статьи пишет, что функция fromUtf8 принимает указатель на char* в котором находится 16 бит или 2 байта.

Но теперь авто статьи использует SIMD-функцию _mm_loadu_si128, которая загружает в регистры 128 бит или 16 байтов - по указанному источнику src, но ведь длинна src всего 2 байта.

Разве так можно делать ? Разве _mm_loadu_si128 не загрузит в регистры мусор, который будет после 2 байта в источнике src ?


Ответы (1 шт):

Автор решения: AR Hovsepyan

Я не читал статью, но тут предельно ясно:

  • Есть указатель на массив символов (источник), и в нем вовсе не 16 бит.
  • Дальше имя __m128i chunk сразу подсказывает намерение встроенного loadu: обрабатывает по кускам символьную строку по 128 бит( по 16 символов UTF-8), потому передается reinterpret_cast<const __m128i*>(src).
  • И, чтобы это было в пределах источника, выполняется в цикле while(len >= 16), и потому _mm_loadu_si128 не загрузит в регистры мусор.
  • Но, с чего вы взяли, что длина src всего байта, я не знаю...
→ Ссылка