我有一段代码在一个大矩阵上运行并计算逐列分箱统计数据,其中二进制数在向量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
的值没有特定的结构/顺序 - 假设纯随机值。
数据量相当大:数百万项和数百列。
查看代码,我假设在以下情况下可以实现最佳性能:
matrix
是行专业,用于更好的缓存位置。count
将作为count[bin][col][val]
进行访问,因此可以优化count[bin][col]
地址的计算,从而更轻松地进行预取等。但是,在将matrix
创建为专栏时,以及按照代码中显示的顺序访问count
时,我获得了最佳效果。
尝试使用选项(1)或(2)会导致约50%的运行时间损失。 这违反了我对缓存局部性和编译器优化,矢量化等的直觉。
任何想法为什么?这真让我感到困惑。
答案 0 :(得分:1)
我有点困惑。在您的示例矩阵中是行主要。你可以分享这两种实现而忽略计数访问吗?
你的内部循环遍历列,所以确实行主要会更好,高速缓存行一次覆盖多个列。
至于计数,你的val取决于矩阵中存储的内容,而列是按顺序排序的,所以如果你以这种方式访问计数:
count[bin][val][col]
如果列中的多个连续行具有相等的val,则从缓存中获取数据。尽管如此访问它:
count[bin][col][val]
你基本上没有机会从缓存中获取数据,因为你在增加col之后跳得太远了。这是我在这部分最好的选择。
您的矩阵(提供val的那个)是否像您想象的那样随机?