2014-01-08 3 views
2

Я хочу использовать инструкцию Intel PCLMULQDQ с встроенной сборкой в ​​моем коде C для умножения двух многочленов, которые являются элементами в GF (2^n). Компилятор - это GCC 4.8.1. Полиномы хранятся в массивах uint32_t (6 полей больших).инструкция PCLMULQDQ в C inline asm

Я уже проверил Интернет, как правильно использовать инструкцию PCLMULQDQ или CLMUL, но не нашел хорошей документации.

Я бы очень оценил простой пример в C и asm того, как умножить два простых многочлена с инструкцией. Кто-нибудь знает, как это сделать?

Кроме того, есть ли какие-либо предпосылки (кроме совместимого процессора), например, включенные библиотеки, параметры компилятора и т. Д.?

+0

Быстрый поиск дал http://download-software.intel.com/sites/default/files/article/165685/clmul-wp-rev-2.01-2012-09-21.pdf –

ответ

0

Я уже нашел решение. Таким образом, для записи:

void f2m_intel_mult(
    uint32_t t, // length of arrays A and B 
    uint32_t *A, 
    uint32_t *B, 
    uint32_t *C 
) 
{ 
    memset(C, 0, 2*t*sizeof(uint32_t)); 
    uint32_t offset = 0; 
    union{ uint64_t val; struct{uint32_t low; uint32_t high;} halfs;} prod; 

    uint32_t i; 
    uint32_t j; 
    for(i=0; i<t; i++){ 
     for(j=0; j<t; j++){ 

      prod.halfs.low = A[i]; 
      prod.halfs.high = 0; 
      asm ("pclmulqdq %2, %1, %0;" 
      : "+x"(prod.val) 
      : "x"(B[j]), "i"(offset) 
      ); 

      C[i+j] = C[i+j]^prod.halfs.low; 
      C[i+j+1] = C[i+j+1]^prod.halfs.high; 
     } 
    } 
} 

Я думаю, что можно использовать регистры 64-разрядные для PCLMULQDQ, но я не мог узнать, как получить эту работу с встроенным ассемблером. Кто-нибудь знает это?
Тем не менее, также можно сделать то же самое со встроенными функциями. (Если вы хотите, чтобы код просто спрашивал.)
Кроме того, можно оптимизировать вычисления дальше с помощью Karatsuba, если вы знаете размер t массивов.

+0

Выход компилятора из это] (https://godbolt.org/g/eaQrRx) ужасно по-разному. Во-первых, каждый 'pclmul' окружен« movq », чтобы скопировать 64-битный целочисленный регистр в/из нижней половины регистра xmm. Во-вторых, операции 'xor' используют 32-разрядный размер операнда вместо того, чтобы сходить на один 64-битный xor с местом назначения памяти. –

+0

И нет, нет формы pclmul, которая работает с целыми/gp-регистрами, [только xmm] (http://www.felixcloutier.com/x86/PCLMULQDQ.html). Было бы намного более эффективно загружать 128 бит данных непосредственно в вектор SSE и использовать 'pclmul' с различными немедленными смещениями для выполнения разных частей умножения. Если вам нужно обнулить «A» до 64-битных элементов, вы можете сделать это в SSE с помощью «punpckldq» с нулевым регистром. (Или SSE4.1 'pmovzx'). На самом деле вы делаете то же самое для B, но неявно. –

+0

Вы должны сделать XOR в 'C', используя операции SSE. (загрузка с C, 'pxor', сохранение назад.) В любом случае, вы должны обязательно сделать это с помощью встроенных функций, а не встроенных asm. Ваш встроенный asm является правильным и безопасным, но вы теряете много производительности. –

Смежные вопросы