2015-12-29 4 views
2

Я скомпилировал фрагмент кода с опцией -xSSE4.1 с использованием компилятора Intel. Когда я посмотрел на сгенерированный файл сборки, я увидел, что были добавлены инструкции AVX, такие как «vpmovzxbw». Но исполняемый файл по-прежнему работает на машинах, которые не поддерживают набор инструкций AVX. Что объясняет это?Инструкции AVX, созданные при указании -xSSE4.1

Вот конкретный фрагмент кода -

C -> src0_8x16b = _mm_cvtepu8_epi16 (src0_8x16b); 

Assembly -> vpmovzxbw xmm4, QWORD PTR [rcx] 

Binary -> 00066 c4 62 79 30 29 

Вот еще один отрывок, где инструкции по сборке использует 3 операнды -

C -> src0_8x16b = _mm_sub_epi16 (src0_8x16b, src1_8x16b); 

Assembly -> vpsubw xmm1, xmm13, xmm11    

Binary -> 000bc c4 c1 11 f9 cb 

Для сравнения, вот разборки генерируется ICC для «Foo» функция (Единственное различие между функцией foo и фрагментом кода выше состоит в том, что фрагмент кода был закодирован с использованием встроенных функций) -

Compiler commands used - 
icc -S -xSSE4.1 -axavx -O3 foo.c 

Function foo - 
void foo(float *x, int n) 
{ 
    int i; 

    for(i=0; i<n; i++) x[i] *= 2.0; 
} 

Autodispatch code - 
testl  $-131072, __intel_cpu_indicator(%rip)   #1.27 
jne  foo.R           #1.27 
testl  $-1, __intel_cpu_indicator(%rip)    #1.27 
jne  foo.A 

Loop in foo.R (AVX variant) - 
vmulps (%rdi,%rcx,4), %ymm0, %ymm1     #3.24 
vmulps 32(%rdi,%rcx,4), %ymm0, %ymm2     #3.24 
vmovups %ymm1, (%rdi,%rcx,4)       #3.24 
vmovups %ymm2, 32(%rdi,%rcx,4)      #3.24 
addq  $16, %rcx          #3.5 
cmpq  %rdx, %rcx         #3.5 
jb  ..B2.12  # Prob 82%      #3.5 

Loop in foo.A (SSE variant) - 
movaps (%rdi,%r8,4), %xmm1       #3.24 
movaps 16(%rdi,%r8,4), %xmm2       #3.24 
mulps  %xmm0, %xmm1         #3.24 
mulps  %xmm0, %xmm2         #3.24 
movaps %xmm1, (%rdi,%r8,4)       #3.24 
movaps %xmm2, 16(%rdi,%r8,4)       #3.24 
addq  $8, %r8          #3.5 
cmpq  %rsi, %r8          #3.5 
jb  ..B3.12  # Prob 82%      #3.5 
+2

http://www.felixcloutier.com/x86/PMOVZX.html Возможно, вы смутитесь с VPMOVZXBW –

+0

pmovzx is sse41. vpmovzxbw - avx. Проверьте [link] (https://software.intel.com/en-us/node/524007) – ashwin

+1

Возможно, он генерирует версию AVX для некоторых вещей, но работает только после выполнения проверки времени выполнения, что система поддерживает AVX ? Опубликуйте отрезанную разборку, включая двоичный машинный код, чтобы мы могли убедиться, что это действительно VEX-кодировка. В идеале, установите контрольную точку в этой инструкции и убедитесь, что она действительно запускается, если у вас есть отладчик на машине перед AVX. –

ответ

2

Процессор Intel компилятор can

генерируют один исполняемый с несколькими уровнями векторизации с -ax флагом,

Например, чтобы генерировать код, который совместим с AVX, SSE4.1 и SSE2 для использования -axAVX -axSSE4.2 -xSSE2.

Поскольку вы скомпилировали с помощью -axAVX -xSSE4.1 Intel выпустила ветвь AVX и ветку SSE4.1, и во время выполнения она определяет, какой набор инструкций доступен и выбирает это.

У Agner Fog есть хорошее описание диспетчера процессора Intel в его Optimizing C++ manaul. См. Раздел «13.7 диспетчеризация процессора в компиляторе Intel». Диспетчер процессора Intel не идеален по нескольким причинам, одним из которых является то, что он плохо работает на AMD, о чем подробно рассказывает Agner. Лично я бы сделал своего собственного диспетчера.


Я составил следующий код с ICC 13,0 с вариантами -O3 -axavx -xsse2

void foo(float *x, int n) { 
    for(int i=0; i<n; i++) x[i] *= 2.0; 
} 

и началом сборки

test  DWORD PTR __intel_cpu_indicator[rip], -131072 #1.27 
    jne  _Z3fooPfi.R         #1.27 
    test  DWORD PTR __intel_cpu_indicator[rip], -1  #1.27 
    jne  _Z3fooPfi.A 

собирается в _Z3fooPfi.R ветви найти основной цикл AVX

..B2.12:      # Preds ..B2.12 ..B2.11 
vmulps ymm1, ymm0, YMMWORD PTR [rdi+rcx*4]   #2.25 
vmulps ymm2, ymm0, YMMWORD PTR [32+rdi+rcx*4]  #2.25 
vmovups YMMWORD PTR [rdi+rcx*4], ymm1     #2.25 
vmovups YMMWORD PTR [32+rdi+rcx*4], ymm2    #2.25 
add  rcx, 16          #2.2 
cmp  rcx, rdx          #2.2 
jb  ..B2.12  # Prob 82%      #2.2 

собирается в _Z3fooPfi.A ветви имеет основной цикл SSE

movaps xmm1, XMMWORD PTR [rdi+r8*4]     #2.25 
movaps xmm2, XMMWORD PTR [16+rdi+r8*4]    #2.25 
mulps  xmm1, xmm0         #2.25 
mulps  xmm2, xmm0         #2.25 
movaps XMMWORD PTR [rdi+r8*4], xmm1     #2.25 
movaps XMMWORD PTR [16+rdi+r8*4], xmm2    #2.25 
add  r8, 8           #2.2 
cmp  r8, rsi          #2.2 
jb  ..B3.12  # Prob 82%      #2.2 
+0

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

+0

@ashwin, ваш код выйдет из строя, если он только сгенерировал инструкции AVX на машине без AVX. Он должен генерировать SSE-код, но вы его еще не нашли. –

+0

Я понимаю, что код должен сработать. Следовательно, мой вопрос :). Если вы просеиваете мои предыдущие комментарии, вы должны были заметить, что я тестировал это на машине SSE42, и все прошло отлично. Вероятно, как вы сказали, я еще не нашел код SSE, но я сомневаюсь, так как я просмотрел разборку, сгенерированную как на Windows, так и на Linux (которые были на двух разных версиях компилятора icc BTW), и это были единственные инструкции, которые я нашел между функцией _begin_ и _end_ – ashwin

2

Я попытался повторить результаты на двух других компиляторов, а именно., GCC и компиляторы V100 Microsoft Visual Studio. Я не смог этого сделать, т. Е. Компиляторы gcc и v100, похоже, генерируют правильные дизассембли. В качестве следующего шага я внимательно рассмотрел различия, если таковые имеются, существовавшие между аргументами компилятора, которые я указал в каждом случае. Оказывается, что, используя компилятор icc, я включил возможность наследовать значения по умолчанию для компиляции этого конкретного файла.Настройки проекта были настроены таким образом, чтобы эта опция была включена -

-xavx 

В результате, когда этот файл был компилируется, настройки, которые я предоставил -

-xSSE4.1 -axavx 

были переопределены бывшим. Это явилось причиной того, что я подробно изложил в своем вопросе.

Прошу прощения за эту ошибку, но я не стану исключать этот вопрос, так как ответ @Zboson's является исключительным.

PS - Я упомянул в одном из своих комментариев, что я смог запустить этот код на машине SSE42. Это связано с тем, что exe, который я запускал на этой машине, действительно совместим с SSE41, поскольку я, по-видимому, использовал exe, сгенерированный с использованием компилятора gcc. Я запустил обработанный icc exe, и это действительно сбой с ошибкой неправильной команды на машине SSE42.

+0

Спасибо за объяснение. В этом есть смысл. –

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

  • Нет связанных вопросов^_^