Инструкция по инструкции Micro-оптимизации SSE

Я заметил, что иногда 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);
10
задан Paul R 27 September 2011 в 09:38
поделиться