C(堆)中的多维数组内存使用

问题描述 投票:2回答:2

我有一个问题,以了解以下代码的内存使用情况:

typedef struct list{
    uint64_t*** entrys;
    int dimension;
    uint64_t len;
} list;

void init_list(list * t, uint64_t dim, uint64_t length, int amount_reg)
{
    t->dimension = dim;
    t->len=length;
    t->entrys = (uint64_t ***) malloc(sizeof(uint64_t**)*length);
    uint64_t i;
   for(i=0;i<length;i++)
   {
       t->entrys[i] = (uint64_t **) malloc(sizeof(uint64_t *)*dim); 
       int j;
       for(j=0;j<dim;j++)
       {
           t->entrys[i][j]=(uint64_t *) malloc(sizeof(uint64_t)*amount_reg);
       }
   }
}

int main()
{
     list * table = (list *) malloc(sizeof(list));
     init_list(table,3,2048*2048,2);
     _getch();
}

我想要做的是分配一个像表[4194304] [3] [2]的uint64_t元素的3d数组。 任务管理器显示内存使用量为560MB。 CO 如果我尝试自己计算内存使用量,我无法理解该值。 这是我的计算(对于x64系统):

2^20 * 8 Byte (first dimension pointers)
+ 2^20 * 3 * 8 Byte (second dimension pointers)
+ 2^20 * 3 * 2 * 8 Byte (for the values itsself)

= 2^20 * 8 Byte * 10 = 80MB

也许我对这个计算完全错了,或者我的代码产生了大量的开销?!

如果是这样,有没有办法让这个程序更有效率?我无法想象像qazxsw poi这样的东西需要如此多的记忆(因为qazxsw poi只是~2^23 uint64_t

c memory-management multidimensional-array heap-memory
2个回答
1
投票

您的代码对2^23*8Byte进行了2²²·4 + 1 = 16777217次调用。对于每个分配的内存区域,64MB会做一些记账。当你对malloc()进行多次调用时,这会增加。您可以通过调用malloc()来减少开销,如下所示:

malloc()

在这里我们只调用malloc()三次,内存使用率从561272 KiB下降到332020 KiB。为什么内存使用率仍然如此之高?因为你在计算中犯了一个错误。分配分配了这么多内存:

  • 条目:void init_list(list * t, int dim, uint64_t length, int amount_reg) { uint64_t ***entries = malloc(sizeof *entries * length); uint64_t **seconds = malloc(sizeof *seconds * length * dim); uint64_t *thirds = malloc(sizeof *thirds * length * dim * amount_reg); uint64_t i, j; t->entrys = entries; for (i = 0; i < length; i++) { t->entrys[i] = seconds + dim * i; for (j = 0; j < dim; j++) t->entrys[i][j] = thirds + amount_reg * j + amount_reg * dim * i; } } = 8·2²²
  • 秒:malloc() = 8·2²²3
  • 三分之一:sizeof(uint64_t**) * length = 8·2²²·3·2

总之,我们有(1 + 3 + 6)·8·2²²= 335544320字节(327680 KiB或320 MiB)的RAM,它与观察到的内存量非常接近。

你怎么能进一步减少这个数额?考虑转置数组,使轴按大小的升序排序。这样你就可以在指针中浪费更少的内存。您还可以考虑仅为值分配空间并手动执行索引计算。这可以加快代码的速度(减少内存访问)并节省内存,但编程很繁琐。


0
投票

4194304不是2 ^ 20,它更像是2 ^ 22,所以你的计算至少是4的因子。你还分配了一组指针来指向其他数据,这需要空间。在您的代码中,第一个malloc分配2048 * 2048个指针,而不是指向那么多项的单个指针。

您还应该使用最佳实践进行动态分配:

1)不要转换malloc返回

2)总是使用sizeof(uint64_t*) * length * dim这样,无论你在表达式中使用了多少个指针级别,都无法获得大小错误。例如。

sizeof(uint64_t) * length * dim * amount_reg
© www.soinside.com 2019 - 2024. All rights reserved.