2016-06-17 1 views
2

ли быстрее вычислить скалярное произведение двух векторов средств вида dpps КОМАНД SSE 4.1 инструкции или с помощью ряда addps, shufps и mulps от SSE 1?Dot характеристики продукта с инструкциями SSE

+2

Связанный: http://stackoverflow.com/q/18499971/1207195, но ничего не лучше, чем хороший старый тест производительности ... –

+2

Есть ли больше контекста для этого? Часто можно избежать ситуации, когда необходимо сделать горизонтальный точечный продукт в первую очередь. – harold

+0

Как? Не могли бы вы привести пример – Philinator

ответ

5

Ответ, вероятно, будет очень контекстуальным и будет зависеть именно от того, где и как он используется в большем потоке кода, а также о том, какое оборудование вы используете.

Исторически, когда Intel представила новые инструкции, они не посвятили много аппаратной области. Если он будет принят и использован достаточно, в будущих поколениях они закладывают больше аппаратных средств. Таким образом, _mm_dp_ps на Penryn не был особенно впечатляющим по сравнению с тем, что он сделал SSE2 с точки зрения производительности ALU. С другой стороны, это требует меньше инструкций в I-кеше, поэтому потенциально может помочь, когда более компактная кодировка будет работать лучше.

Настоящая проблема с _mm_dp_ps является частью SSE 4.1, вы не можете рассчитывать на то, что она поддерживается на любом современном ПК (Valve's Hardware Hardware Survey привязывает ее примерно на 85% для геймеров). Поэтому вам приходится писать защищенные кодовые пути, а не прямой код, и это обычно стоит больше, чем выгоды, получаемые от использования инструкции.

Где полезно, если вы создаете двоичный код для ЦП, который, как гарантируется, будет поддерживать его. Например, если вы строите с /arch:AVX (или даже /arch:AVX2), либо потому, что вы нацеливаете фиксированную платформу, такую ​​как Xbox One, или создаете несколько версий EXE/DLL, вы можете предположить, что SSE 4.1 также будет поддерживаться.

Это эффективно, что делает DirectXMath:

inline XMVECTOR XMVector4Dot(FXMVECTOR V1, FXMVECTOR V2) 
{ 
#if defined(_XM_NO_INTRINSICS_) 

    XMVECTOR Result; 
    Result.vector4_f32[0] = 
    Result.vector4_f32[1] = 
    Result.vector4_f32[2] = 
    Result.vector4_f32[3] = V1.vector4_f32[0] * V2.vector4_f32[0] + V1.vector4_f32[1] * V2.vector4_f32[1] + V1.vector4_f32[2] * V2.vector4_f32[2] + V1.vector4_f32[3] * V2.vector4_f32[3]; 
    return Result; 

#elif defined(_M_ARM) || defined(_M_ARM64) 

    float32x4_t vTemp = vmulq_f32(V1, V2); 
    float32x2_t v1 = vget_low_f32(vTemp); 
    float32x2_t v2 = vget_high_f32(vTemp); 
    v1 = vpadd_f32(v1, v1); 
    v2 = vpadd_f32(v2, v2); 
    v1 = vadd_f32(v1, v2); 
    return vcombine_f32(v1, v1); 

#elif defined(__AVX__) || defined(__AVX2__) 

    return _mm_dp_ps(V1, V2, 0xff); 

#elif defined(_M_IX86) || defined(_M_X64) 

    XMVECTOR vTemp2 = V2; 
    XMVECTOR vTemp = _mm_mul_ps(V1,vTemp2); 
    vTemp2 = _mm_shuffle_ps(vTemp2,vTemp,_MM_SHUFFLE(1,0,0,0)); 
    vTemp2 = _mm_add_ps(vTemp2,vTemp); 
    vTemp = _mm_shuffle_ps(vTemp,vTemp2,_MM_SHUFFLE(0,3,0,0)); 
    vTemp = _mm_add_ps(vTemp,vTemp2); 
    return _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(2,2,2,2)); 

#else 
    #error Unsupported platform 
#endif 
} 

Это, конечно, предполагает, что вы собираетесь использовать «скалярную» результат скалярного произведения в дополнительных векторных операций. По соглашению DirectXMath возвращает такие скаляры «splatted» через обратный вектор.

См DirectXMath: SSE4.1 and SSE4.2

UPDATE: Хотя не столь вездесущи, как поддержка SSE/SSE2, вам может потребоваться поддержка SSE3 за исключением случаев, вы не строят с /arch:AVX или /arch:AVX2 и попробовать:

inline XMVECTOR XMVector4Dot(FXMVECTOR V1, FXMVECTOR V2) 
{ 
    XMVECTOR vTemp = _mm_mul_ps(V1,V2); 
    vTemp = _mm_hadd_ps(vTemp, vTemp); 
    return _mm_hadd_ps(vTemp, vTemp); 
} 

При этом не ясно, что hadd - это большая часть выигрышей в большинстве случаев, по меньшей мере, для точечного продукта по сравнению с SSE/SSE2, добавлением и перетасовкой.

+1

'dpps' все еще занимает 4 часа в кэше uop на процессорах Intel SnB-семейства, что часто является более ценным ресурсом, чем I-кеш L1. Тем не менее, это похоже на победу в UOP по сравнению с резервом для этого случая. В отличие от 'haddps' для горизонтальной суммы, все это происходит всего в 4 раза. –

+0

'' haddps'' является SSE3, который технически не требуется для процессоров x64 или Windows 8.1/Windows 10, хотя Valve Survey показывает его на уровне 99%, поэтому он эффективно поддерживается везде для геймеров. См. [DirectXMath: SSE3 и SSSE3] (https://blogs.msdn.microsoft.com/chuckw/2012/09/11/directxmath-sse3-and-ssse3/) –

+0

@Peter. Как версия SSE3 сравнивается с 'отступать'? –

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