加速聚集

时间:2017-01-06 05:42:12

标签: c++ optimization simd avx2

我有一个计算产生一个系数向量,并返回该向量的点积与从大数组中取得的数据向量。为了加快速度,我使用AVX2 SIMD内在函数一次为8个向量执行此操作。问题是大部分时间最终被聚合操作消耗得到点积的数据。

我尝试了不同的方法来实现聚集,内在似乎效果最好。我非常感谢有关加快这项工作的一些建议。

这是一幅草图:

__m256 Compute(__m256 input)
{
    __m256 coefficients[56] = ComputeCoefficients(input);

    __m256i indices = ComputeIndices(input);

    __m256 sum = _mm256_setzero_ps();
    for (size_t i = 0; i != 56; ++i)
    {
        __m256 data = _mm256_i32gather_ps(bigArray + i, indices, sizeof(float)); // 
        sum = _m256_fmadd_ps(coefficients[i], data, sum);
    }
    return sum;
}

1 个答案:

答案 0 :(得分:1)

我首先要确保您使用的是最新的英特尔处理器。英特尔已投入大量工程来改进收集指令。

这就是说,这并不神奇。如果有缓存未命中,您将为它们付出代价。

我会尝试在没有SIMD指令的情况下编写相同的代码。它的速度大致相同吗?如果是,那么您的内存访问受限制的可能性很大。矢量化很好地解决了计算限制,以及以矢量大小为单位编写和存储数据,但即使在原则上,也不能期望对随机访问和缓存问题的约束问题有很大的帮助。 / p>

您的代码反复拨打VPGATHERDPS。根据Agner Fog的说法,该指令的延迟为12个周期,每4个周期一个指令的吞吐量。当然,延迟是最好的情况,缓存未命中会增加延迟。

您应该对代码进行基准测试,并确保每个循环迭代接近4个周期。主循环应该在大约300个循环中完成,并且所有事情都说得很快。

你没有告诉我们很多关于你的问题,但我们可以猜测它比300个周期慢得多。如果是这样,那么你可能有缓存问题。如果您的表很大并且您随机访问它,那么这是一个难题。如果您需要更好的性能,可能需要重新设计问题。