Вопрос

Я работаю над автоматической векторизацией с помощью GCC.Я не могу использовать встроенные функции или атрибуты из-за требований клиента.(Я не могу получить пользовательский ввод для поддержки векторизации)

Если информация о выравнивании массива, который может быть векторизован, неизвестна, GCC вызывает проход для «управления версиями цикла».Управление версиями цикла будет выполняться при векторизации цикла на деревьях.Если цикл определен как векторизуемый, а ограничения на выравнивание данных или зависимость данных мешают ему (поскольку они не могут быть определены во время компиляции), то будут созданы две версии цикла.Это векторизованные и невекторизованные версии цикла, а также проверки во время выполнения на выравнивание или зависимость для контроля того, какая версия выполняется.

Мой вопрос: как нам обеспечить соблюдение согласованности?Если я нашел цикл, который можно векторизовать, мне не следует создавать две версии цикла из-за отсутствия информации о выравнивании.

Например.Рассмотрим приведенный ниже код

short a[15]; short b[15]; short c[15];
int i;

void foo()
{
    for (i=0; i<15; i++)
    {
      a[i] = b[i] ;
    }
}

Свалка деревьев (варианты:-fdump-tree-optimized -ftree-vectorize)

<SNIP>
     vector short int * vect_pa.49;
     vector short int * vect_pb.42;
     vector short int * vect_pa.35;
     vector short int * vect_pb.30;

    bb 2>:
     vect_pb.30 = (vector short int *) &b;
     vect_pa.35 = (vector short int *) &a;
     if (((signed char) vect_pa.35 | (signed char) vect_pb.30) & 3 == 0)    ;; <== (A)
       goto <bb 3>;
     else
       goto <bb 4>;

    bb 3>:
</SNIP>

В «bb 3» генерируется версия векторизованного кода.При 'bb 4' генерируется код без векторизации.Это делается путем проверки выравнивания (оператор «А»).Теперь, не используя встроенные функции и другие атрибуты, как мне получить только векторизованный код (без этой проверки выравнивания во время выполнения).

Это было полезно?

Решение

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

Вы также можете использовать posix_memalign() функция, если вы используете систему, которая ее поддерживает.Наконец, обратите внимание, что malloc() всегда будет выделять память в соответствии с размером наибольшего встроенного типа, обычно 8 байт для типа double.Если тебе не нужно ничего лучшего, то malloc должно хватить.

Редактировать:Если вы измените свой код распределения, чтобы эта проверка была истинной (т.overlocate, как было предложено выше), компилятор должен сделать это, не обусловливая код цикла.Если вам нужно выравнивание по 8-байтовой границе, это будет что-то вроде a = (a + 7) & ~3;.

Другие советы

Я получаю только одну версию цикла, используя ваш точный код со следующими параметрами: gcc -march=core2 -c -O2 -fdump-tree-optimized -ftree-vectorize vec.c

Моя версия GCC gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8).

GCC делает здесь что-то умное.Это заставляет массивы a и b быть выровненым по 16 байт.Он не делает этого, чтобы c, предположительно потому, что c никогда не используется в векторизуемом цикле.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top