Действительно базовый SSE - PullRequest
       11

Действительно базовый SSE

1 голос
/ 02 ноября 2011

У меня есть очень простая программа, которую я пытаюсь улучшить производительность.Один способ, который, как я знаю, поможет, - это использовать SSE3 (так как машина, на которой я работаю, поддерживает это), но я абсолютно не знаю, как это сделать.Вот фрагмент кода (c ++):

int sum1, sum2, sum3, sum4;
for (int i=0; i<length; i+=4) {
  for (int j=0; j<length; j+=4) {
    sum1 = sum1 + input->value[i][j];
    sum2 = sum2 + input->value[i+1][j+1];
    sum3 = sum3 + input->value[i+2][j+3];
    sum4 = sum4 + input->value[i+3][j+4];    
  {
}

Я немного читал об этом и понимаю идею, но совершенно не представляю, как это реализовать.Может кто-нибудь помочь мне, пожалуйста?Я думаю, что это довольно просто, особенно для моей простой программы, но иногда самое трудное - начать.

Спасибо!

1 Ответ

6 голосов
/ 02 ноября 2011

На самом деле, в вашем случае, это не так просто.В настоящее время ваш код НЕ векторизован.(по крайней мере, без значительных преобразований цикла)

Причина этого заключается в том, что вы изменяете индекс i также во внутреннем цикле.Это исключает возможность векторизации итерации j, поскольку ячейки памяти больше не являются смежными и находятся в разных строках матрицы.(поскольку вы, кажется, бежите вниз по матрице по диагонали)

Однако у меня возникает ощущение, что вы пытаетесь суммировать все элементы в вашей матрице, и вы действительно хотели, чтобы ваш цикл был таким (иу вас тоже было несколько опечаток):

int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
for (int i=0; i<length; i++) {
  for (int j=0; j<length; j+=4) {
    sum1 = sum1 + input->value[i][j];
    sum2 = sum2 + input->value[i][j+1];
    sum3 = sum3 + input->value[i][j+2];
    sum4 = sum4 + input->value[i][j+3];    
  }
}

int total = sum1 + sum2 + sum3 + sum4;

Если это то, что вы хотели, то это очень векторизовано.В C / C ++ с использованием встроенных функций это можно сделать следующим образом, используя только SSE2:

__m128i sum = _mm_setzero_si128();
for (int i=0; i<length; i++) {
  for (int j=0; j<length; j+=4) {
    __m128i val = _mm_load_si128(&input->value[i][j]);
    sum = _mm_add_epi32(sum,val);
  }
}

Обратите внимание, что будут применяться ограничения на выравнивание.И еще большее ускорение можно получить, развернув петлю.

...