2016-01-14 1 views
2

Мой ноутбук поддерживает только AVX (расширенное расширение векторов), но не поддерживает AVX2. Для AVX 128-битные xmm * регистры уже были расширены до 256-битных регистров ymm * для арифметики с плавающей запятой. Тем не менее, я тестировал, что все версии Visual Studio (с 2010 по 2015 год) не используют ymm * регистры под/arch: оптимизация AVX, хотя они делают это под/arch: оптимизация AVX2.Visual Studio 2010 - 2015 не использует регистры ymm * для оптимизации AVX

Ниже приведена разборка для простого цикла. Программа скомпилирована с/arch: AVX в сборке релизов, причем все параметры оптимизации включены.

float a[10000], b[10000], c[10000]; 
    for (int x = 0; x < 10000; x++) 
1000988F xor   eax,eax 
10009891 mov   dword ptr [ebp-9C8Ch],ecx 
     c[x] = (a[x] + b[x])*b[x]; 
10009897 vmovups  xmm1,xmmword ptr c[eax] 
100098A0 vaddps  xmm0,xmm1,xmmword ptr c[eax] 
100098A9 vmulps  xmm0,xmm0,xmm1 
100098AD vmovups  xmmword ptr c[eax],xmm0 
100098B6 vmovups  xmm1,xmmword ptr [ebp+eax-9C78h] 
100098BF vaddps  xmm0,xmm1,xmmword ptr [ebp+eax-9C78h] 
100098C8 vmulps  xmm0,xmm0,xmm1 
100098CC vmovups  xmmword ptr [ebp+eax-9C78h],xmm0 
100098D5 add   eax,20h 
100098D8 cmp   eax,9C40h 
100098DD jl   ComputeTempo+67h (10009897h) 


    const int winpts = (int)(window_size*sr+0.5); 
100098DF vxorps  xmm1,xmm1,xmm1 
100098E3 vcvtsi2ss xmm1,xmm1,ecx 

Я также проверил, что я могу использовать регистры ymm * для дальнейшего ускорения моей программы без сбоев. Я сделал это с использованием IMM-функций, например. _mm256_mul_ps.

Может ли разработчик компилятора Microsoft дать объяснение? Или, может быть, это одна из причин, почему Visual Studio дает более медленные коды, чем компилятор gcc/g ++?

+1

Пробовал ли цикл, где компилятор знает, что массивы выровнены по 32B? Я замечаю, что он использует нестандартные команды загрузки/хранения. Кроме того, процессоры AMD хуже с 256-битным AVX-кодом, чем с 128-битным AVX-кодом, особенно. Piledriver имеет огромные проблемы с 256b магазинами. Поэтому, если вы не сказали компилятору оптимизировать для конкретной микроархитектуры, векторы 128b «более безопасны». –

+0

Я тестировал void 'void foo (float * a, float * b, float * c) {for (int i = 0; i <10000; i ++) c [i] = (a [i] + b [i]) * б [I]; } 'в MSVC 2015 с' cl/c/O2/arch: AVX' и использует 'ymm'. Я не знаю, в чем проблема. –

+2

@PeterCordes, нет никакого штрафа за использование нестандартных инструкций загрузки с AVX. Существует штраф (но не большой) для того, чтобы память не была выровнена на 32B, но Clang и MSVC не настраиваются для этого (но GCC и ICC делают). –

ответ

4

Я сделал текстовый файл vec.cpp

//vec.cpp 
void foo(float *a, float *b, float *c) { 
    for (int i = 0; i < 10000; i++) c[i] = (a[i] + b[i])*b[i]; 
} 

пошел в командной строке с помощью Visual Studio с поддержкой 2015 x86 x64 и сделал

cl /c /O2 /arch:AVX /FA vec.cpp 

посмотрел на файл vec.asm и я вижу

[email protected]: 
    vmovups ymm0, YMMWORD PTR [rax-32] 
    lea rax, QWORD PTR [rax+64] 
    vmovups ymm2, ymm0 
    vaddps ymm0, ymm0, YMMWORD PTR [rcx+rax-96] 
    vmulps ymm2, ymm0, ymm2 
    vmovups YMMWORD PTR [r8+rax-96], ymm2 
    vmovups ymm0, YMMWORD PTR [rax-64] 
    vmovups ymm2, ymm0 
    vaddps ymm0, ymm0, YMMWORD PTR [rcx+rax-64] 
    vmulps ymm2, ymm0, ymm2 
    vmovups YMMWORD PTR [r8+rax-64], ymm2 
    sub rdx, 1 
    jne SHORT [email protected] 
    vzeroupper 

Проблема в том, что вы компилируете в 32-битном режиме. Используя ту же функцию выше, но компилируя в 32-битном режиме, я получаю

[email protected]: 
    lea eax, DWORD PTR [ebx+esi] 
    lea ecx, DWORD PTR [ecx+32] 
    lea esi, DWORD PTR [esi+32] 
    vmovups xmm1, XMMWORD PTR [esi-48] 
    vaddps xmm0, xmm1, XMMWORD PTR [ecx-32] 
    vmulps xmm0, xmm0, xmm1 
    vmovups XMMWORD PTR [edx+ecx-32], xmm0 
    vmovups xmm1, XMMWORD PTR [esi-32] 
    vaddps xmm0, xmm1, XMMWORD PTR [eax] 
    vmulps xmm0, xmm0, xmm1 
    vmovups XMMWORD PTR [eax+edx], xmm0 
    sub edi, 1 
    jne SHORT [email protected] 
+1

Ну, но почему компилятор не использует регистры YMM при генерации 32-битного кода? YMM0-YMM7, безусловно, доступны в режиме x86-32. –

+0

@CodyGray, я понятия не имею. : почему для Visual Studio по умолчанию используется 32-разрядный режим, даже когда ОС 64-разрядная? Мне неприятно идти в диспетчер конфигурации после создания нового проекта и говорить об использовании x64. Я не очень хорошо разбираюсь в графическом интерфейсе GUI Visual Studio, что удобно, поэтому я в основном использую командную строку ([это помогло] (https://www.youtube.com/watch?v=Ee3EtYb8d1o)) в любом случае. ss отладчик Visual Studio хорош, но я использую printf и assembly для отладки в любом случае. –

+0

Ваш второй вопрос легко ответить --- многие приложения по-прежнему скомпилированы для 32-разрядной версии для максимальной совместимости. Не у всех есть 64-разрядные процессоры и/или работает 64-разрядные операционные системы. У самой Windows по-прежнему имеется 32-разрядная версия, которая не поддерживает 64-разрядные приложения. –

0

Да, это была проблема с 32-разрядной/64-разрядной ошибкой. Компиляция в режиме x64 не вызывает проблем. Однако по какой-то причине моя программа должна быть скомпилирована в 32-битном режиме, поскольку это был какой-то плагин, в котором поддерживается только 32-разрядная версия. Тем не менее, все еще противоречиво, что даже в 32-битном режиме установка/arch: AVX2 позволит компилятору получить доступ к ymm * -регресам.

Из спецификации Intel, http://www.felixcloutier.com/x86/ADDPS.html, он говорит, что «в 64-битном режиме, с использованием префикса REX в виде REX.R позволяет эту инструкцию для получения доступа к дополнительным регистрам (XMM8-XMM15).» Также в http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html указано, что 32-разрядные программы могут обращаться к регистрам ymm * в 32-разрядных и 64-битных операционных системах. Единственным ограничением является то, что в 32-битном режиме у вас нет доступа к xmm8-xmm15 или ymm8-ymm15, потому что инструкции короче. Вот почему я могу вручную использовать встроенные функции для доступа к ymm * -регресам, не вызывая краха команды.

В заключение, если не существует некоторых процессоров, поддерживающих только AVX, но не AVX2, возникнут проблемы с доступом к регистрам ymm * в 32-битном режиме (что уже доказано, что это не так), выше не требуется. И я все еще надеюсь, что компилятор Visual C++ может быть улучшен, чтобы сделать эту опцию оптимизации доступной, поскольку многие компьютеры поддерживают только AVX, но не AVX2, а использование ymm * регистров может удвоить производительность арифметики с плавающей запятой.

+0

Обычная процедура, когда кто-то отвечает на ваш вопрос, должен принять ответ, если вы думаете, что это отвечает на ваш вопрос. Вы, кажется, не знаете об этом, потому что вы не сделали этого для ответа @PaulR [здесь] (http://stackoverflow.com/a/34586817/2542702). –

+0

Извините, я довольно новичок в stackoverflow, я только узнал, что большой тик под рангами/рангом вниз также доступен для кликов. Отмечено! - :) – xuancong84

+0

Нет проблем. Я действительно не полностью ответил на ваш вопрос, так что было бы хорошо, если бы вы не приняли ответ. Вы также можете изменить принятый ответ в случае, если кто-то позже ответит на ваш вопрос больше на ваше удовлетворение. –

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