Есть ли разница между SVML и обычными внутренними функциями квадратного корня?

# #c #intel #sse #intrinsics #sse2

Вопрос:

Есть ли какая — либо разница в точности или производительности между обычными sqrtps/pd или версией SVML:

      __m128d _mm_sqrt_pd (__m128d a) [SSE2]
     __m128d _mm_svml_sqrt_pd (__m128d a) [SSE?]
 
      __m128 _mm_sqrt_ps (__m128 a) [SSE]
     __m128 _mm_svml_sqrt_ps (__m128 a) [SSE?]
 

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

Были ли эти функции SVML созданы до SSE2? Или есть разница в точности?

Комментарии:

1. Если у вас есть компилятор, который поддерживает их, вы можете использовать его в __m128 foo(__m128 v) оболочке и посмотреть, соответствует ли он sqrtps xmm0,xmm0 / ret или нет. IDK, в чем был бы смысл этих версий SVML.

2. Трудно представить, что они предоставляют __m128d тип и sqrt для него на процессоре без SSE2. Большинство компиляторов даже не определяют, __m128d включен ли SSE2 (попробуйте 32-разрядную сборку -mno-sse2 ), или в компиляторах, таких как ICC и MSVC, использование __m128d подразумевает использование SSE2. И было бы довольно бессмысленно поддерживать вектор SIMD для выполнения эмулированных sqrt с двойной точностью, но не добавлять / sub / mul / div, и эмуляция будет медленнее, чем просто использование x87 для 2 элементов отдельно. Поэтому я думаю, что мы можем исключить эту догадку.

Ответ №1:

Я проверил кодовое поколение в MSVC.

  • _mm_svml_sqrt_pd компилируется в вызов функции; вызываемая функция состоит из одного sqrtpd , за которым следует ret
  • _mm_svml_sqrt_ps компилируется в вызов функции; вызываемая функция состоит из одного sqrtps , за которым следует ret
  • _mm_sqrt_pd и _mm_sqrt_ps встроенные компоненты компилируются в встроенные sqrtpd и sqrtps

Возможное объяснение (просто угадайте): SVML предназначался для отправки ЦП, но в версии, скомпилированной для MSVC, эта отправка ЦП отключена. Цель может состоять в том, чтобы реализовать его по-другому для Xeon Phi, версия Xeon Phi может быть не включена в сборку MSVC SVML.


Скриншот: введите описание изображения здесь


При использовании компилятора Intel он использует svml_dispmd.dll , и есть фактическая функция отправки (реальный косвенный переход ff 25 42 08 00 00 ), которая для меня заканчивается в v sqrtpd

Комментарии:

1. Является ли косвенный вызов функции просто обычным механизмом DLL, потому что код находится в библиотеке DLL SVML? Я предполагаю, что вы тестировали машину с AVX , и она все еще sqrtpd не работала vsqrtpd , так что похоже, что это действительно так глупо, и они никогда не должны были предоставлять эти функции.

2. Хм, интересно, может ли версия Xeon Phi использовать AVX512ER vrsqrt28ps для получения приближения, для которого не требуется итерация Ньютона-Рафсона для одинарной точности? IIRC, фактические инструкции sqrt довольно медленные в KNL, и вы собираетесь использовать AVX512ER vfixupimmps для обработки таких случаев, как 0.

3. @PeterCordes, функции не находятся в DLL; даже несмотря на то , что я компилирую с /MD , так что время выполнения C находится в DLL, они статически связаны как exe. Возможно , я неправильно использовал косвенный термин: есть вызов функции e8 af 0c 00 00 , затем по целевому адресу происходит переход e9 0b 00 00 00 , и по этому адресу происходит фактическая реализация.

4. Ах, хорошо, это не совсем «косвенный вызов», как вы получили бы для динамического связывания DLL. (Может ли это разрешиться во время динамической связи на основе функций процессора, как это может сделать динамическая связь Linux? Вот как glibc разрешает memcmp и т. Д. к версиям для процессоров AVX2 или чего-либо еще без каких-либо накладных расходов на каждый вызов выше того, что уже накладывает динамическое связывание.) call rel32 для a jmp rel32 больше похоже на заглушку / оболочку PLT Linux (хотя PLT обычно использует a jmp [mem] ). IDK, если бы SVML мог переписать это jmp на основе функций процессора; можете ли вы сказать, находится ли это на странице памяти, что в какой-то момент оно может переназначить чтение/запись?

5. Возможно, дело действительно в том, чтобы использовать другую кодировку для Xeon Phi, но поскольку Visual Studio не пытается нацелиться на Xeon Phi, в версии библиотеки SVML, поставляемой вместе с ней, опущена отправка, но рудиментарные функции отправки все еще присутствуют, поэтому я вижу этот относительный jmp; Я добавил скриншот к ответу