Распараллелить код C с помощью SSE/AVX

я хотел бы распараллелить свой существующий код с помощью команд SSE/AVX. Я полный нуб в этих инструкциях

Снипер кода, о котором идет речь, следующий

static void inline enc_round(uint32_t b0[4], uint32_t b1[4], const uint32_t **kpp)
{
    for (int n = 0; n<4; n++)
    {
        b0[n] = crypto_ft_tab[0][byte(b1[n], 0)] ^
            crypto_ft_tab[1][byte(b1[(n + 1) & 3], 1)] ^
            crypto_ft_tab[2][byte(b1[(n + 2) & 3], 2)] ^
            crypto_ft_tab[3][byte(b1[(n + 3) & 3], 3)] ^ *(*kpp + n);
    }
    *kpp += 4;
}

Со следующими определениями типов

const uint32_t crypto_ft_tab[4][256]
static inline uint8_t byte(const uint32_t x, const unsigned n)

Я хотел бы распараллелить логический ANDS

EDIT: извините, я имел в виду побитовое XOR

Любое предложение, как лучше всего начать или с каких команд я должен начать?

заранее спасибо


person user3694354    schedule 04.08.2014    source источник
comment
Я не вижу никаких логических И — я вижу побитовые XOR — это то, что вы имеете в виду?   -  person Paul R    schedule 04.08.2014
comment
@PaulR, может быть, он имел в виду часть (n + 1) & 3?   -  person Scis    schedule 04.08.2014
comment
Ах, побитовое И — может быть — этот вопрос нуждается в некотором уточнении.   -  person Paul R    schedule 04.08.2014
comment
@PaulR vOv да... Вы можете отредактировать (снова :)), чтобы вопрос был более ясным (потому что логических and, очевидно, вообще нет).   -  person Scis    schedule 04.08.2014
comment
Конечно - я только отредактировал теги - я позволю ОП исправить содержимое, так как я только догадываюсь о реальных требованиях.   -  person Paul R    schedule 04.08.2014
comment
Извините, я немного запутался, когда писал текст вчера. Я, конечно, имел в виду побитовые XOR   -  person user3694354    schedule 05.08.2014
comment
Моя основная проблема заключается в том, как разместить crypto_ft_tab в регистре, когда одна часть crypto_ft_tab имеет размер 256 бит, а на crypto_ft_tab их четыре. я думаю, что наивным способом было бы загрузить каждую часть crypto_ft_tab в один отдельный регистр, таким образом, я заполню все 16 частями crypto_ft_tab, и больше не останется регистров для работы.   -  person user3694354    schedule 14.08.2014
comment
1) Если это AES, готовы ли вы использовать собственные инструкции AES? 2) Вы говорите AVX, но это AVX1 или AVX2? В случае AVX2 ваши операции добавления, операции AND и LUT могут быть все векторизованы частично благодаря операциям Haswell gather (хотя сами по себе они не особенно быстры). Или вы можете использовать SSE2 pshufb. 3) Для окончательных XOR вам нужно будет выполнить последовательность перетасовок и XOR на стадии log2 (n) для выполнения этого сокращения.   -  person Iwillnotexist Idonotexist    schedule 30.10.2014


Ответы (1)


В GCC и Visual Studio вы можете легко использовать встроенные функции компилятора для создания инструкций SSE и AVX.

Список доступных инструкций можно найти на веб-сайте Intel здесь: https://software.intel.com/sites/landingpage/IntrinsicsGuide/

При использовании SSE2 это будет выглядеть примерно так:

// load values 1 to 4 as 16 byte blocks from the given addresses:
__m128i value1 = _mm_loadu_((__m128i*)address1);
__m128i value2 = _mm_loadu_((__m128i*)address2);
__m128i value3 = _mm_loadu_((__m128i*)address3);
__m128i value4 = _mm_loadu_((__m128i*)address4);
// build xor
__m128i result = _mm_xor_si128(value1, value2);
result = _mm_xor_si128(result, value3);
result = _mm_xor_si128(result, value4);
// store the result somewhere into memory
_mm_storeu_si128((__m128i*)addressForResult);

Обратите внимание, что каждая переменная __m128i содержит весь 16-байтовый вектор ваших данных. Используя встроенные функции AVX2, вы даже можете обрабатывать данные блоками по 32 байта.

person rvjr    schedule 28.08.2015