C / C ++如何将3维数组存储在内存中以及遍历它的最快方法是啥

Posted

技术标签:

【中文标题】C / C ++如何将3维数组存储在内存中以及遍历它的最快方法是啥【英文标题】:C/C++ How a 3 dimensional array is stored in memory and what is the fastest way to traverse itC / C ++如何将3维数组存储在内存中以及遍历它的最快方法是什么 【发布时间】:2014-02-15 03:43:58 【问题描述】:

我试图了解 3 维数组是如何存储在内存中的,以及 std:vector 的存储方式之间的区别。

这是我理解的存储它们的方式,和 std::vectors 的存储方式相同,不同之处在于它们充分利用了内存块 a[0][0][0] a[0][0][1] a[0][0][2]... a[0][1][0] a[0][1] [1] ... a[1][0][0] a[1][0][1]...

我的目标是找出最有效的遍历和数组方式。

例如,我有数组:

v[1000][500][3];

那么如何更高效地遍历呢?

for(i = 0; i < 1000; i++)

    for(j = 0; j < 500; j++)
    
       for(k = 0; k < 3; ++k)
       
           //some operation
       

    

或者将数组声明为更有效;

v[3][500][1000]

并遍历为

for(i = 0; i

 

是否有任何 CL 工具可以可视化数组的存储方式?

【问题讨论】:

3D 矢量是什么意思? 3维a[10][20][30] 这仍然是一个数组。在您的问题中,您区分了 3D 数组和 3D 矢量。 向量是指多个元素存储在一个内存块中。例如在数组中,一个元素存储在一个内存块中,但在一个内存块中的向量中存储多个元素,具体取决于内存块的数据类型和大小。我想知道向量的元素是否以与数组元素相同的顺序存储在内存中,以及遍历它的最有效方法是什么。 请编辑您的问题以说明您的意思。并指定您是否在谈论 std::vector 因为 std::vector 只能是一维。 【参考方案1】:

你说得对,内存中的数组表示值是连续的。所以初始化为 0 的 int v[2][2][2] 看起来像:

[[[0, 0], [0, 0]], [[0, 0], [0, 0]]]

就性能而言,您希望尽可能接近地访问数据以避免数据缓存未命中,因此首先迭代最外层维度是一件好事,因为它们彼此相邻。

在您的第一个示例中可能发生的事情是编译器可能会优化内部循环(如果满足正确的条件)并展开它,这样您就可以通过跳过分支来节省一些时间。

由于您的两个示例都已经以正确的方式迭代,我会说对其进行分析,看看哪个更快。


std::vector 还将其元素连续存储在内存中,但由于它是一维的,因此默认情况下应用局部性(前提是您不是随机迭代)。向量的好处是它们可以增长而数组不能(无论如何都是自动的)。

【讨论】:

【参考方案2】:

当内存地址是连续的(例如,编译时间数组a[][][]),遍历多维数组最有效的方法是使用a pointera[i][j][k] 实际上是 &amp;a[0][0][0]+(i*j*k + j*k + k)。因此,将指针p初始化为起始地址,然后调用*(p++)

int main() 
    int a[2][3]=1,2,3,4,5,6;
    int *p = &a[0][0];
    for( int i=0; i<6; ++i )
        cout<<*(p++)<<endl;
    
    return 0;

【讨论】:

而声明v[3][500][1000]就变成了3 * 500 * 1000字节的连续内存。因此,它在记忆中是一样的。两种解决方案的操作次数相同。【参考方案3】:

使其可见:

#include <iostream>

    int main()
    
        int a[][3] =   0, 1, 2 ,  3, 4, 5  ;
        int* p = reinterpret_cast<int*>(a);
        for(unsigned i = 0; i < 6; ++i) 
            std::cout << *(p + i);
        
        std::cout << std::endl;
        return 0;
    

显示一行主要顺序 - 请参阅:http://en.wikipedia.org/wiki/Row-major_order

有了这个,您应该逐行迭代以利用缓存。在更高维度 N 中,你会得到类似的结果,其中每个元素代表一个维度为 N-1 的数据块

【讨论】:

以上是关于C / C ++如何将3维数组存储在内存中以及遍历它的最快方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

3D 数组如何存储在 C 中?

c语言中怎么把一个数组清空

C语言中如何计算一个数组占内存多少空间

c语言问题:c语言中二维数组在内存中怎样存储?

c关于数组所占内存大小问题

如何将数据动态存储在C中的链表中?