我有一段代码在大矩阵上运行并计算逐列分箱统计数据,其中二进制数在向量b中给出. 代码就像这样(某事): for (item = 0; item items; item++) { uint8 bin = binvec[item]; for (col = 0; col columns; col++) {
代码就像这样(某事):
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是row major,用于更好的缓存局部性.
> count将作为count [bin] [col] [val]访问,因此count [bin] [col]的地址计算可以优化,允许更容易的预取等.
但是,在创建矩阵作为列主要时,我获得了最佳性能,并按照代码中出现的顺序访问计数.
尝试使用选项(1)或(2)会导致约50%的运行时间损失.
这违背了我对缓存局部性和编译器优化,矢量化等的直觉.
知道为什么?这真让我感到困惑.
我有点困惑.在您的示例矩阵中是行主要.你可以分享这两种实现而忽略计数访问吗?你的内部循环遍历列,所以确实行主要会更好,高速缓存行一次覆盖多个列.
至于计数,你的val取决于矩阵中存储的内容,而列按顺序排序,所以如果你以这种方式访问计数:
count[bin][val][col]
如果列中的多个连续行具有相等的val,则从缓存中获取数据.尽管如此访问它:
count[bin][col][val]
你有很多机会从缓存中获取数据,因为你在增加col之后跳得太远了.这是我在这部分最好的选择.
您的矩阵(提供val的那个)是否像您想象的那样随机?