때때로 MSVC 2010이 SSE 지침을 전혀 변경하지 않는다는 것을 알고 있습니다. 컴파일러가 최선을 다룰 때부터 루프 내에서 명령어 순서에 신경 쓸 필요가 없다고 생각했습니다.SSE 마이크로 최적화 명령 주문
어떻게 생각하나요? 무엇이 가장 좋은 명령 순서를 결정합니까? 일부 명령어는 다른 명령어보다 지연 시간이 길고 일부 명령어는 CPU 레벨에서 병렬/비동기로 실행될 수 있음을 알고 있습니다. 어떤 메트릭스가 컨텍스트와 관련이 있습니까? 어디에서 찾을 수 있습니까?
나는 그러나 이러한 프로파일은 내가 뒤에 이론뿐만 아니라 emperical 결과를 알고 싶습니다 (의 VTune XE) 비싸고 , 내가 을 프로파일 링하여이 문제를 피할 수있는 것을 알고있다.
또한 소프트웨어 프리 페치 (_mm_prefetch
)에 신경을 써야합니까, 아니면 CPU가 나보다 나은 직업이라고 생각할 수 있습니까?
다음과 같은 기능이 있다고 가정 해 보겠습니다. 지침 중 일부를 삽 입해야합니까? 스트림 전에 상점을해야합니까, 모든로드를 순서대로 수행 한 다음 계산 등을할까요? 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);
나는 이것에 대한 해답이 측정 된 테스트에 있어야한다고 생각한다. x86은 꽤 오랫동안 [OOE] (http://en.wikipedia.org/wiki/Out-of-order_execution)를 가지고 있었지만 주문에 관계없이이 사건을 최적으로 처리 할 수 있습니다. – Flexo
테스트가 항상 최선입니다. 그러나이 경우에는 다소 비싼 프로파일 러가 필요합니다. VTune XE. 경험적 결과보다는 그 배경에 관한 이론에 대해 더 알고 싶습니다. OOE는 얼마나 멀리 떨어져 있습니까? 메모리 대기 시간이나 명령 대기 시간입니까? 다시 주문하면 OOE가 병렬로 실행할 수있는 명령을 처리합니까? – ronag
릴리스 빌드 어셈블러 출력을 게시 할 수 있습니까? 컴파일러가 이것을 어떻게하는지 보는 것은 흥미로울 것입니다. – Skizz