Использование пакета кода Keccak в Visual Studio - PullRequest
0 голосов
/ 04 ноября 2018

Я скачал пакет кода Keccak (сейчас XKCP), потому что мне интересны все функции, которые он предоставляет, и я хотел бы использовать их в своем «проекте», так мы его назовем.

Проблема в том, что я программирую свой проект с использованием Microsoft Visual Studio Community 2017 ... Я объясню:

На самом деле, я пытаюсь внедрить Keyak Lake в свой проект и, особенно, реализацию Keyak Lake, которая использует ускорения SIMD. Но код, который поставляется с KCP (Keccak Code Package), предназначен для GCC, а не для VS, и, следовательно, его трудно скомпилировать в Visual Studio, и в основном из-за приведений (__m128d) и (__m128i) в макросы, используемые в реализации SIMD на озере Кейак. GCC разрешает такие виды приведения, но Visual Studio не делает так, чтобы код не работал как есть, вы должны переработать его, используя _mm_castpd_si128 и такие ...

Итак, вот что я попробовал: Я заменил все макросы их эквивалентным кодом, используя -E в GCC. Фактически, я получил код после работы препроцессора, поэтому все макросы развернуты, полностью записаны, а затем я заменил все приведения, которые не были приняты Visual Studio, их внутренними эквивалентами. И, наконец, я мог бы получить код для компиляции в Visual Studio, но он все еще не работает нормально.

Вот ошибка:

void KeccakP1600_Permute_12rounds(void *state)
{    
    //All the variables like Abae, Cae, Akimo etc... are ALL __m128i variables
    //state is an unsigned char[200]

    UINT64 *stateAsLanes = (UINT64*)state;
    Abae = _mm_load_si128((const __m128i *)&(stateAsLanes[0]));
    Aba = Abae;
    Abe = _mm_unpackhi_epi64(Abae, Abae);
    Cae = Abae;
    Abio = _mm_load_si128((const __m128i *)&(stateAsLanes[2]));
    Abi = Abio;
    Abo = _mm_unpackhi_epi64(Abio, Abio);
    Cio = Abio;
    Abu = _mm_loadl_epi64((const __m128i *)&(stateAsLanes[4]));
    Cua = Abu;
    Agae = _mm_loadu_si128((const __m128i *)&(stateAsLanes[5]));
    Aga = Agae;
    Abuga = _mm_unpacklo_epi64(Abu, Aga);
    Age = _mm_unpackhi_epi64(Agae, Agae);
    Abage = _mm_unpacklo_epi64(Aba, Age);
    Cae = _mm_xor_si128(Cae, Agae);
    Agio = _mm_loadu_si128((const __m128i *)&(stateAsLanes[7]));
    Agi = Agio;
    Abegi = _mm_unpacklo_epi64(Abe, Agi);
    Ago = _mm_unpackhi_epi64(Agio, Agio);
    Abigo = _mm_unpacklo_epi64(Abi, Ago);
    Cio = _mm_xor_si128(Cio, Agio);
    Agu = _mm_loadl_epi64((const __m128i *)&(stateAsLanes[9]));
    Abogu = _mm_unpacklo_epi64(Abo, Agu);
    Cua = _mm_xor_si128(Cua, Agu);
    Akae = _mm_load_si128((const __m128i *)&(stateAsLanes[10]));
    Aka = Akae;
    Ake = _mm_unpackhi_epi64(Akae, Akae);
    Cae = _mm_xor_si128(Cae, Akae);
    Akio = _mm_load_si128((const __m128i *)&(stateAsLanes[12]));
    Aki = Akio;
    Ako = _mm_unpackhi_epi64(Akio, Akio);
    Cio = _mm_xor_si128(Cio, Akio);
    Akuma = _mm_load_si128((const __m128i *)&(stateAsLanes[14]));
    Cua = _mm_xor_si128(Cua, Akuma);
    Ame = _mm_loadl_epi64((const __m128i *)&(stateAsLanes[16]));
    Akame = _mm_unpacklo_epi64(Aka, Ame);
    Cae = _mm_xor_si128(Cae, _mm_unpackhi_epi64(Akuma, Akame));
    Amio = _mm_loadu_si128((const __m128i *)&(stateAsLanes[17]));
    Ami = Amio;
    Akemi = _mm_unpacklo_epi64(Ake, Ami);
    Amo = _mm_unpackhi_epi64(Amio, Amio);
    Akimo = _mm_unpacklo_epi64(Aki, Amo);
    Cio = _mm_xor_si128(Cio, Amio);
    Amu = _mm_loadl_epi64((const __m128i *)&(stateAsLanes[19]));
    Akomu = _mm_unpacklo_epi64(Ako, Amu);
    Cua = _mm_xor_si128(Cua, Amu);
    Asase = _mm_load_si128((const __m128i *)&(stateAsLanes[20]));
    Cae = _mm_xor_si128(Cae, Asase);
    Asiso = _mm_load_si128((const __m128i *)&(stateAsLanes[22]));
    //Error here, last line. Access violation reading location.

Дело в том, что когда оптимизация компилятора не включена, код работает нормально, без ошибок, но как только вы включаете Full Speed ​​Optimization, появляется нарушение чтения при нарушении прав доступа. Не говоря уже о том, что этот код работает на GCC независимо от оптимизации.

У вас могут быть некоторые решения для нарушения чтения или даже некоторые решения о том, как превратить этот «только код GCC» в компилируемый код Visual Studio.

1 Ответ

0 голосов
/ 04 ноября 2018

Предположительно stateAsLanes выровнено на 16. _mm_load_si128((const __m128i *)&(stateAsLanes[22])); выполняет 128-разрядную загрузку, требуемую для выравнивания, из смещенного адреса.

Вы уверены, что было в оригинальном источнике? В любом случае, это должно быть loadu, а не load, чтобы сообщить компилятору, что он не выровнен.

Вы не используете _mm_castpd_si128 где-либо в этом коде, поэтому неясно, что вы изменили или почему вы должны это изменить. Он был сломан и для GCC / clang, который использовал бы movdqa даже в неоптимизированном коде.

В MSVC он, по-видимому, ломается с оптимизацией, поскольку MSVC складывает нагрузку в операнд памяти для некоторой более поздней инструкции ALU; IIRC, когда MSVC и ICC должны использовать автономную нагрузку mov, они обычно используют movdqu невыровненную нагрузку. Это, безусловно, объясняет поведение, которое вы видите, даже при том, что это заставит код работать медленнее, чем необходимо в Core 2.

...