Как обнаружить Xeon Phi (Приземление рыцарей)

Инженеры Intel написали, что мы должны использовать VZEROUPPER / VZEROALL, чтобы избежать дорогостоящего перехода в состояние без VEX на всех процессорах, включая будущий процессор Xeon, но не на Xeon Phi: https://software.intel.com/pt-br/node/704023

Еще люди замерили и выяснили, что VZEROUPPER и VZEROALL стоят дорого на Knights Landing:

36 тактов для обеих инструкций в 64-битном режиме (30 тактов в 32-битном режиме).

См. Ссылку выше.

Итак, мой код будет следующим, если я только что использовал ymm0 и ymm1:

if [we are running on a Xeon Phi]
     vpxor       ymm0,ymm0,ymm0
     vpxor       ymm1,ymm1,ymm1
else
     vzeroall
endif

Как я могу обнаружить Xeon Phi (процессоры Knights Landing и более поздние версии Xeon Phi) для реализации вышеуказанного кода?

Теперь у нас есть следующая ситуация с VZEROUPPER / VZEROALL:

  1. Эти инструкции не нужны и очень дороги для Xeon Phi Knight Landing. 36 тактов для обеих инструкций в 64-битном режиме (30 тактов в 32-битном режиме).
  2. Эти инструкции очень дешевы и необходимы для процессоров Xeon и Core (Skylake / Kaby Lake) и будут необходимы для Xeon в обозримом будущем, чтобы избежать дорогостоящего перехода в состояние, отличное от VEX.

В рекламных материалах утверждается, что Xeon Phi (Knights Landing) полностью совместим с другими процессорами Xeon.

Есть ли надежный способ обнаружить Xeon Phi, чтобы избежать VZEROUPPER / VZEROALL?

Есть статья «Как определить приземление рыцарей. Поддержка AVX-512 (процессор Intel® Xeon Phi ™) »Джеймса Р., обновлено 22 февраля 2016 г., но в нем сосредоточены только конкретные новые инструкции, которые стали доступны в Knights Landing. Таким образом, все еще не очень ясно, что касается переходов VEX.

Было бы неплохо узнать, планирует ли Intel реализовать бит CPUID, чтобы показать, дорого обходится ли состояние, отличное от VEX? Например:

  • Бит установлен в 0 - переходы между состояниями VEX являются дорогостоящими, но VZEROUPPER / VZEROALL дешевы и должны использоваться для очистки состояния;
  • Бит установлен в 1 - штрафа за переход нет, VZEROUPPER / VZEROALL не требуется.

В упомянутой выше статье об обнаружении Knights Landing предлагается проверить биты AVX-512F + CD + ER + PF, представленные в Knights Landing.

Таким образом, код предлагает проверить все эти биты сразу, и если все они установлены, то мы находимся в Приземлении Рыцарей:

uint32_t avx2_bmi12_mask = (1 << 16) | // AVX-512F
                           (1 << 26) | // AVX-512PF
                           (1 << 27) | // AVX-512ER
                           (1 << 28);  // AVX-512CD

Было бы неплохо узнать, планирует ли Intel добавить все эти биты в простые процессоры Xeon (не Phi) или Core в ближайшем будущем, чтобы они также поддерживали функции AVX-512F + CD + ER + PF, представленные в Knight Landding?

Если процессор Xeon и Core будет поддерживать AVX-512F + CD + ER + PF, мы не сможем отличить Xeon от Xeon Phi.

Пожалуйста, порекомендуйте.


person Maxim Masiutin    schedule 09.06.2017    source источник
comment
Наверняка вы знаете целевой ЦП во время компиляции, поэтому можете просто использовать макрос препроцессора?   -  person Paul R    schedule 10.06.2017
comment
@PaulR, нет, мы не знаем целевой процессор во время компиляции, мы пишем массовое приложение, которое можно запускать практически где угодно, а Knights Landing можно использовать в качестве основного процессора для запуска любого приложения.   -  person Maxim Masiutin    schedule 10.06.2017
comment
Верно, но вы можете скомпилировать версии ваших оптимизированных функций для конкретного процессора и использовать диспетчер во время выполнения - это то, что Intel делает в своих оптимизированных библиотеках. Тогда ваш код будет более эффективным, так как ему не нужно будет выполнять какие-либо проверки во время выполнения (кроме первого вызова диспетчера).   -  person Paul R    schedule 10.06.2017
comment
@PaulR - в любом случае я должен каким-то образом обнаружить Xeon Phi, хотя бы один раз при запуске, и я понятия не имею, как его надежно обнаружить.   -  person Maxim Masiutin    schedule 10.06.2017
comment
Помогает ли это: software.intel.com/ en-us / article /?   -  person Paul R    schedule 10.06.2017
comment
@PaulR - спасибо! Я обновил вопрос, чтобы решить проблему, которую вы подняли относительно того, как обнаружить статью.   -  person Maxim Masiutin    schedule 11.06.2017
comment
Разве вы не можете проверить поддерживаемые функции, а затем cpuid.family == B sandpile.org/x86/cpuid.htm   -  person ta.speot.is    schedule 11.06.2017
comment
@PaulR - Хорошо, подойдет! Спасибо, Пол!   -  person Maxim Masiutin    schedule 11.06.2017
comment
Следует обратить внимание на то, что Skylake Xeon (Purley) будет поддерживать AVX512 - хотя я не знаю, есть ли у него штраф переключения VEX.   -  person Paul R    schedule 11.06.2017
comment
Если вы правильно напишете код, это не проблема. Вам нужно выполнить эту дорогостоящую инструкцию только один раз, а затем, если вы никогда не смешиваете инструкции VEX и не-VEX, вам не нужно использовать ее снова. В худшем случае вы тратите ~ 30 циклов один раз на KNL, который (1) не является очень распространенным процессором, а (2) является достаточно быстрым процессором, чтобы эти потраченные впустую циклы можно было легко восполнить.   -  person Cody Gray    schedule 12.06.2017
comment
@CodyGray: правда, если вы никогда не обращаетесь к системным или сторонним библиотекам - к сожалению, они могут содержать код SSE, отличный от VEX. Сказав это, код SIMD должен работать с достаточной степенью детализации, чтобы накладные расходы в 30 циклов не составляли большого труда - если вы смешиваете вызовы системы / библиотеки и код SIMD так тонко, что это имеет значение, то вы, вероятно, не собираетесь в любом случае работает с максимальной эффективностью.   -  person Paul R    schedule 15.06.2017
comment
@PaulR - спасибо, я уже решил префикс VEX для всех инструкций, которые я могу, а что касается других библиотек - я позабочусь о том, чтобы они были детализированными, поэтому, как вы написали, 30 циклов не представляет большого труда. Я решил вообще воздержаться от использования VZEROUPPER / VZEROALL. Я провел тесты и выяснил, что если ваш код является детализированным, выдача даже одного VZEROUPPER один раз во всей программе (однопоточная) делает весь последующий код, отличный от VEX, на 30% медленнее, чем если бы мы вообще не вызывали VZEROUPPER после Код VEX. Какой парадокс! Если хотите, могу опубликовать результаты тестов. Это известное поведение?   -  person Maxim Masiutin    schedule 15.06.2017
comment
@PaulR - VZEROUPPER замедляет выполнение следующего кода, отличного от VEX, только в Kaby Lake и Skylake. В предыдущих архитектурах микропроцессоров Intel это не имеет значения.   -  person Maxim Masiutin    schedule 15.06.2017


Ответы (1)


Если вы специально хотите проверить, находится ли в KNL (а не более общий вопрос «Имеет ли процессор, на котором я работаю, функцию X?»), Вы можете сделать это, просмотрев «Расширенное семейство», «Семейство» и «Модель». "поля в% eax после вызова cpuid с% eax == 1 и% ecx == 0. Код C ++, подобный приведенному ниже, выполнит свою работу.

Однако, как неявно указывают другие, это очень специфический тест, и, например, он не сработает на будущих ядрах Knights, поэтому вам, вероятно, будет лучше сделать то, что было предложено, и проверить функции AVX-512, которых нет в Xeon, поэтому AVX512-ER и AVX512-PF. (Конечно, такие инструкции могут появиться в будущих Xeon, так что это не гарантировано в долгосрочной перспективе, но, цитируя Кейнса: «В долгосрочной перспективе мы все мертвы» :-))

class cpuidState
{
    uint32_t orig_eax;                      /* Values sent in to the cpuid instruction */
    uint32_t orig_ecx;

    uint32_t eax;                           /* Values received back from it. */
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;

    void cpuid()
    {
        __asm__ __volatile__("cpuid"
                             : "+a" (eax), "=b" (ebx), "+c" (ecx), "=d" (edx));
    }

    void update (uint32_t eaxVal, uint32_t ecxVal)
    {
        orig_eax = eaxVal;
        orig_ecx = ecxVal;
        eax      = eaxVal;
        ecx      = ecxVal;
        cpuid();
    }

    void ensureCorrectLeaf(uint32_t eaxVal, uint32_t ecxVal)
    {
        if (orig_eax != eaxVal || orig_ecx != ecxVal)
            update (eaxVal, ecxVal);
    }

 public:
    cpuidState() : orig_eax (-1), orig_ecx(-1) { }

    // Include the Extended Model in the test. Without it we see some Xeons as KNL :-(
    bool onKNL()            { ensureCorrectLeaf(1,0); return (eax & 0x0f0ff0) == 0x50670; }    
};
person Jim Cownie    schedule 12.06.2017