2009-08-08 3 views
7

Я пишу программу на C, которая должна выполнять быстрые математические вычисления. Я использую встроенные инструкции по сборке SSE для получения некоторого действия SIMD (с использованием чисел с плавающей запятой с двойной точностью). Я компилирую GCC в Linux.Получите GCC, чтобы сохранить регистр SSE во всей функции, которая использует inline asm

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

Чтобы уточнить с каким-то кодом:

struct vect2 { 
    fltpt x; 
    fltpt y; 
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */ 
typedef struct vect2 vect2_t; 


void function() 
{ 
    /* get a specific value set up in xmm1, and keep it there for the 
    * rest of the loop. */ 
    for(int i = 0, i<N; i++){ 
     asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
     ); 
    } 
} 

Я пытался сделать что-то с «регистром» ключевым словом. Но если я не ошибаюсь, похоже, что я могу сохранить указатель этой структуре (в общем регистре). Это нужно будет откладывать каждую итерацию, тратя драгоценное время.

register vect2_t hVect asm("xmm1") = {h, h}; 
/* Gives error: data type of 'hVect' isn't suitable for a register */ 

register vect2_t *hVect2 asm("rax"); 
*hVect2 = (vect2_t){h,h}; 
/* Seems to work, but not what I'm looking for */ 

Я не просто хотел бы предположить, что GCC не изменит XMM1 регистр, это слишком много «демонов, вылетающие из своего носа» рода вещи :-). Поэтому я надеюсь, что есть правильный способ сделать это.

ответ

8

Я думаю, что решение здесь заключается в том, чтобы gcc осознал, что ваш тип vec2_t на самом деле является вектором; то вы можете просто вычислить значение петли-инвариантна и рассматривать его как обычную переменную (кроме компилятора знает, что это тип вектора):

typedef double vec2_t __attribute__ ((vector_size (16))); 

void function() 
{ 
    /* get a specific value set up, e.g. */ 
    vec2_t invariant; 
    asm("some calculations, soring result in invariant." 
     : "=x" (invariant)); 

    for(int i = 0; i<N; i++){ 
    asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
      : "x" (invariant) // and other SSE arguments 
     ); 
    } 
} 

Я только что собрал это с помощью простого вычисления внутри цикла и по меньшей мере, с уровнем оптимизации 1 значение invariant хранится в регистре XMM во время цикла.

(Все это предполагает, что вы не должны нуждаетесь в, ваш инвариант цикла в явном регистре XMM и что вы можете использовать распределение обычных регистров GCC).

3

Я думаю, что лучше оставить задание регистратора компилятору. Возможно, он лучше отслеживает это, чем вы. GCC уже использует расширения SSE, но если вы уверены, что знаете лучше, используйте функции GCC __builtin. Честно говоря, я сомневаюсь, что вы сделаете это быстрее.

Удачи!

Эти сайты, вероятно, интересны для просмотра.

GCC X86 Built-in functions

Working with SIMD with GCC

3

Я привык работать со сборкой и C, и что я хотел бы сделать здесь является то, что я хотел бы написать целую функцию в сборке. Если у вас есть гибкая система make, я рекомендую отдельно установить функцию ASM и связать ее с вашим приложением. Единственная проблема заключается в том, что функция не может быть встроена компилятором.

void function (void); // C

внешняя функция «C» (пустота); // C++