Я заметил, что иногда MSVC 2010 вообще не заменяет инструкции SSE. Я думал, что мне не нужно было заботиться о порядке инструкций внутри моей петли, поскольку компилятор обрабатывает это лучшее, что, похоже, не так.
Как я должен думать об этом? Что определяет лучший порядок обучения? Я знаю, что некоторые инструкции имеют более высокую задержку, чем другие, и что некоторые инструкции могут работать параллельно / Async на уровне ЦП. Какие метрики актуальны в контексте? Где я могу их найти?
Я знаю, что я мог избежать . Избегайте Этот вопрос благодаря профилированию, однако такие профилировщики дорогие (VTUNE XE) и Я хотел бы знать теорию позади этого , а не только исходящие результаты.
Также я должен заботиться о предварительной выборке программного обеспечения ( _mm_prefetch
) или могу предположить, что ЦП сделает лучшую работу, чем я?
позволяет сказать, что у меня есть следующая функция. Должен ли я переплетать некоторые из инструкций? Должен ли я сделать магазины перед ручьями, выполните все нагрузки по порядку, а затем делать расчеты и т. Д. Нужно ли рассмотреть USWC против USWC, а также временные против нересурс?
auto cur128 = reinterpret_cast<__m128i*>(cur);
auto prev128 = reinterpret_cast<const __m128i*>(prev);
auto dest128 = reinterpret_cast<__m128i*>(dest;
auto end = cur128 + count/16;
while(cur128 != end)
{
auto xmm0 = _mm_add_epi8(_mm_load_si128(cur128+0), _mm_load_si128(prev128+0));
auto xmm1 = _mm_add_epi8(_mm_load_si128(cur128+1), _mm_load_si128(prev128+1));
auto xmm2 = _mm_add_epi8(_mm_load_si128(cur128+2), _mm_load_si128(prev128+2));
auto xmm3 = _mm_add_epi8(_mm_load_si128(cur128+3), _mm_load_si128(prev128+3));
// dest128 is USWC memory
_mm_stream_si128(dest128+0, xmm0);
_mm_stream_si128(dest128+1, xmm1);
_mm_stream_si128(dest128+2, xmm2);;
_mm_stream_si128(dest128+3, xmm3);
// cur128 is temporal, and will be used next time, which is why I choose store over stream
_mm_store_si128 (cur128+0, xmm0);
_mm_store_si128 (cur128+1, xmm1);
_mm_store_si128 (cur128+2, xmm2);
_mm_store_si128 (cur128+3, xmm3);
cur128 += 4;
dest128 += 4;
prev128 += 4;
}
std::swap(cur, prev);