使用行主要订单时,为什么会看到性能下降?

时间:2017-06-23 10:35:58

标签: c caching optimization nested-loops simd

我有一段代码在一个大矩阵上运行并计算逐列分箱统计数据,其中二进制数在向量b中给出。

代码如下所示:

for (item = 0; item < items; item++) {
    uint8 bin = binvec[item];
    for (col = 0; col < columns; col++) {
        int idx = item * items_stride + col * cols_stride;
        uint8 val = matrix[idx];
        float x = matrix2[idx];
        count[bin][val][col] += x;
    }
}

假设在编译时已知列数。 matrix的值没有特定的结构/顺序 - 假设纯随机值。 数据量相当大:数百万项和数百列。

查看代码,我假设在以下情况下可以实现最佳性能:

  1. matrix是行专业,用于更好的缓存位置。
  2. count将作为count[bin][col][val]进行访问,因此可以优化count[bin][col]地址的计算,从而更轻松地进行预取等。
  3. 但是,在将matrix创建为专栏时,以及按照代码中显示的顺序访问count时,我获得了最佳效果。

    尝试使用选项(1)或(2)会导致约50%的运行时间损失。 这违反了我对缓存局部性和编译器优化,矢量化等的直觉。

    任何想法为什么?这真让我感到困惑。

1 个答案:

答案 0 :(得分:1)

我有点困惑。在您的示例矩阵中是行主要。你可以分享这两种实现而忽略计数访问吗?

你的内部循环遍历列,所以确实行主要会更好,高速缓存行一次覆盖多个列。

至于计数,你的val取决于矩阵中存储的内容,而列是按顺序排序的,所以如果你以这种方式访问​​计数:

count[bin][val][col]

如果列中的多个连续行具有相等的val,则从缓存中获取数据。尽管如此访问它:

count[bin][col][val]

你基本上没有机会从缓存中获取数据,因为你在增加col之后跳得太远了。这是我在这部分最好的选择。

您的矩阵(提供val的那个)是否像您想象的那样随机?