我注意到有时MSVC 2010根本没有重新排序SSE指令。因为编译器处理的最好,我认为我不必关心循环内部的指令顺序,这似乎并不是这种情况。SSE微优化指令订单
我应该怎么想?什么决定最佳指令顺序?我知道一些指令比其他指令具有更高的延迟,并且某些指令可以在CPU级别上并行/异步运行。在上下文中哪些指标是相关的?我可以在哪里找到它们?
我知道我可以避免通过分析这个问题,但是这样的廓线仪价格昂贵(VTune™可视化XE)和我想知道它背后的理论,而不仅仅是emperical结果。
另外我应该关心软件预取(_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