我试图通过 SSE 和 AVX 提高复制操作的性能:
#include <immintrin.h>
const int sz = 1024;
float *mas = (float *)_mm_malloc(sz*sizeof(float), 16);
float *tar = (float *)_mm_malloc(sz*sizeof(float), 16);
float a=0;
std::generate(mas, mas+sz, [&](){return ++a;});
const int nn = 1000;//Number of iteration in tester loops
std::chrono::time_point<std::chrono::system_clock> start1, end1, start2, end2, start3, end3;
//std::copy testing
start1 = std::chrono::system_clock::now();
for(int i=0; i<nn; ++i)
std::copy(mas, mas+sz, tar);
end1 = std::chrono::system_clock::now();
float elapsed1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count();
//SSE-copy testing
start2 = std::chrono::system_clock::now();
for(int i=0; i<nn; ++i)
{
auto _mas = mas;
auto _tar = tar;
for(; _mas!=mas+sz; _mas+=4, _tar+=4)
{
__m128 buffer = _mm_load_ps(_mas);
_mm_store_ps(_tar, buffer);
}
}
end2 = std::chrono::system_clock::now();
float elapsed2 = std::chrono::duration_cast<std::chrono::microseconds>(end2-start2).count();
//AVX-copy testing
start3 = std::chrono::system_clock::now();
for(int i=0; i<nn; ++i)
{
auto _mas = mas;
auto _tar = tar;
for(; _mas!=mas+sz; _mas+=8, _tar+=8)
{
__m256 buffer = _mm256_load_ps(_mas);
_mm256_store_ps(_tar, buffer);
}
}
end3 = std::chrono::system_clock::now();
float elapsed3 = std::chrono::duration_cast<std::chrono::microseconds>(end3-start3).count();
std::cout<<"serial - "<<elapsed1<<", SSE - "<<elapsed2<<", AVX - "<<elapsed3<<"\nSSE gain: "<<elapsed1/elapsed2<<"\nAVX gain: "<<elapsed1/elapsed3;
_mm_free(mas);
_mm_free(tar);
有用。然而,虽然测试循环中的迭代次数 - nn - 增加了,但 simd-copy 的性能增益却降低了:
nn=10:SSE 增益=3,AVX 增益=6;
nn=100:SSE 增益=0.75,AVX 增益=1.5;
nn=1000:SSE 增益=0.55,AVX 增益=1.1;
任何人都可以解释提到的性能下降影响的原因是什么,是否建议手动对复制操作进行矢量化?
原文由 gorill 发布,翻译遵循 CC BY-SA 4.0 许可协议
问题是您的测试在迁移硬件中使基准测试变得困难的某些因素方面做得很差。为了测试这一点,我制作了自己的测试用例。像这样的东西:
输出:
所以在这种情况下,AVX 比
std::copy
快很多。当我将测试用例更改为..时会发生什么请注意,除了测试的顺序外,绝对没有任何变化。
哇!这怎么可能? CPU 需要一段时间才能达到全速,因此稍后运行的测试具有优势。这个问题现在有 3 个答案,包括一个“已接受”的答案。但只有投票数最少的那个才是正确的。
这就是为什么基准测试很难的原因之一,你永远不应该相信任何人的微基准,除非他们已经包含了他们设置的详细信息。不仅仅是代码可能出错。省电功能和奇怪的驱动程序可能会完全搞乱您的基准测试。有一次,我通过切换不到 1% 的笔记本电脑提供的 bios 开关来测量性能差异 7 倍。