Оптимизация SSE-кода - PullRequest
       18

Оптимизация SSE-кода

6 голосов
/ 17 октября 2011

В настоящее время я разрабатываю C-модуль для Java-приложения, которое нуждается в некоторых улучшениях производительности (см. Повышение производительности сетевого кодирования-кодирования для фона).Я попытался оптимизировать код с использованием SSE-встроенных функций, и он выполняется несколько быстрее, чем Java-версия (~ 20%).Тем не менее, это все еще не достаточно быстро.

К сожалению, мой опыт оптимизации C-кода несколько ограничен.Поэтому я хотел бы получить некоторые идеи о том, как улучшить текущую реализацию.

Внутренняя петля, которая составляет горячую точку, выглядит следующим образом:

for (i = 0; i < numberOfGFVectorsInFragment; i++)   {

        // Load the 4 GF-elements from the message-fragment and add the log of the coefficeint to them.
        __m128i currentMessageFragmentVector = _mm_load_si128 (currentMessageFragmentPtr);
        __m128i currentEncodedResult = _mm_load_si128(encodedFragmentResultArray);

        __m128i logSumVector = _mm_add_epi32(coefficientLogValueVector, currentMessageFragmentVector);

        __m128i updatedResultVector = _mm_xor_si128(currentEncodedResult, valuesToXor);
        _mm_store_si128(encodedFragmentResultArray, updatedResultVector);

        encodedFragmentResultArray++;
        currentMessageFragmentPtr++;
    }

Ответы [ 2 ]

7 голосов
/ 17 октября 2011

Даже не глядя на сборку, я могу сразу сказать, что узкое место связано с доступом к памяти из 4 элементов и с операциями упаковки _mm_set_epi32. Внутренне, _mm_set_epi32, в вашем случае, вероятно, будет реализовано как серия unpacklo/hi инструкций.

Большая часть "работы" в этом цикле заключается в упаковке этих 4 обращений к памяти. В отсутствие SSE4.1 я бы сказал, что цикл может быть быстрее не векторным, а развернутым.

Если вы хотите использовать SSE4.1, вы можете попробовать это. Это может быть быстрее, это не так:

    int* logSumArray = (int*)(&logSumVector);

    __m128i valuesToXor = _mm_cvtsi32_si128(expTable[*(logSumArray++)]);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 1);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 2);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 3);

Я предлагаю развернуть цикл как минимум на 4 итерации и перемежать все инструкции, чтобы дать этому коду шанс на хорошую работу.

Что вам действительно нужно, так это инструкции Intel AVX2 по сбору / рассеянию. Но это через несколько лет ...

1 голос
/ 17 октября 2011

Может быть, попробовать http://web.eecs.utk.edu/~plank/plank/papers/CS-07-593/. Функции с "регион" в их именах, предположительно, быстро.Кажется, они не используют никаких специальных наборов инструкций, но, возможно, они были оптимизированы другими способами ...

...