首页 > 解决方案 > 重新排序矢量数据的有效方法(解释为 3D 数组)

问题描述

我正在开发一个用 C++ 编写的应用程序,它必须处理存储在连续内存空间中的一些数据,这些数据被解释为 3D 数组。为了高效的数据处理,我必须改变内存中的数据顺序。

所以这里有一个例子:原始数据位于内存中,我可以通过数据指针 ( ) 访问数据,该数据指针 ( ) 被解释为 3D数组uint16_t*并具有以下维度
xSize=4, ySize=4, zSize=3
,y,z )

d_ 0,0,0 | d_ 1,0,0 | d_ 2,0,0 | d_ 3,0,0 | d_ 0,1,0 | d_ 1,1,0 | d_ 2,1,0 | d_ 3,1,0 | .... | d_ 3,0,2 | d_ 3,1,2 | d_ 3,2,2 | d_ 3,3,2 |

现在我想按 z,y,x 的顺序获取数据:

d_ 0,0,0 | d_ 0,0,1 | d_ 0,0,2 | d_ 0,1,0 | d_ 0,1,1 | d_ 0,1,2 | .... | d_ 2,3,2 | d_ 3,3,0 | d_ 3,3,1 | d_ 3,3,2 |

我用以下循环做了一个实现:

for (uint32_t z = 0; z < zSize; z++) {
    for (uint32_t y = 0; y < ySize; y++) {
        for (uint32_t x = 0; x < xSize; x++) {
            uint32_t readPos = z * xSize * ySize + y * xSize + x;
            uint32_t outPos = y * xSize * zSize + x * zSize + z;
            *(dataOutPtr + outPos) = *(dataInPtr + readPos);
        }
    }
}

有谁知道如何加快这个算法?是否可以在并发执行中执行某些部分,或者是否有人知道重新排序 3D 数据的另一种解决方案?

标签: c++c++11

解决方案


这必然是一个野蛮的算法。您的循环在源中具有良好的缓存局部性,或者在目标中具有良好的缓存局部性,但不是两者兼而有之。具有讽刺意味的是,这可能也是您重新排列数据的原因,以便在使用时获得更合适的缓存位置,但在您真正完成之前,重新排列原始布局会减慢您的速度。

显然,您必须访问每个元素,并且您最内层的循环体的性能与将要获得的性能差不多。

可能有可能并行化这一点——其他人将不得不探索这一点,因为我在那里没有相关知识——但从基本的 C++ 角度来看,我认为你已经在尽你所能。至少,除非您可以预处理或修复源数据,或者除非您可以完全不进行重新排列(例如,如果您实际上不关心缓存位置,因此可以简单地将索引方案更改为外观)。


推荐阅读