【发布时间】:2023-03-09 13:40:01
【问题描述】:
我有以下 AVX 和 Native 代码:
__forceinline double dotProduct_2(const double* u, const double* v)
{
_mm256_zeroupper();
__m256d xy = _mm256_mul_pd(_mm256_load_pd(u), _mm256_load_pd(v));
__m256d temp = _mm256_hadd_pd(xy, xy);
__m128d dotproduct = _mm_add_pd(_mm256_extractf128_pd(temp, 0), _mm256_extractf128_pd(temp, 1));
return dotproduct.m128d_f64[0];
}
__forceinline double dotProduct_1(const D3& a, const D3& b)
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
以及相应的测试脚本:
std::cout << res_1 << " " << res_2 << " " << res_3 << '\n';
{
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < (1 << 30); ++i)
{
zx_1 += dotProduct_1(aVx[i % 10000], aVx[(i + 1) % 10000]);
}
std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::cout << "NAIVE : " << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() << '\n';
}
{
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < (1 << 30); ++i)
{
zx_2 += dotProduct_2(&aVx[i % 10000][0], &aVx[(i + 1) % 10000][0]);
}
std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::cout << "AVX : " << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() << '\n';
}
std::cout << math::min2(zx_1, zx_2) << " " << zx_1 << " " << zx_2;
好吧,所有数据都按 32 对齐。(D3 与 __declspec... 和 aVx arr 与 _mm_malloc()..) 而且,正如我所看到的,本机变体与 AVX 变体相等/或更快。我无法理解它的正常行为?因为我认为 AVX 是“超级快”......如果不是,我该如何优化它?我在 MSVC 2015(x64) 上使用 arch AVX 编译它。另外,我的硬件是intel i7 4750HQ(haswell)
【问题讨论】:
-
发布 MSVC 使用它们制作的 ASM。它可能会使用比
vhaddpd更有效的方式自动矢量化。理想情况下,它将 FMADDPD 用于向量累加器并保存所有水平求和以供结束。如果 MSVC 没有优化掉您手动矢量化的随机播放,那么它不会很快。请参阅stackoverflow.com/questions/6996764/… 了解更多关于为什么hadd是错误的随机播放。 -
更不用说在获得可靠的基准之前您无法调查性能。
-
这是ASM代码(这部分够了吗?):sun9-11.userapi.com/c840724/v840724207/bfbd/kN62Ipo6TZ8.jpg
-
AVX 不是问题,你只是用错了。像往常一样,将水平部分保存在末尾。
-
@DesSpigel:意思是:在循环中垂直做部分点积,然后在最后做一个最终的水平和。
标签: c++ performance simd avx