【问题标题】:How to manipulate dynamic multidimensional-array in C如何在 C 中操作动态多维数组
【发布时间】:2011-08-29 23:38:36
【问题描述】:

我需要分配一个大的多维数组为char a[x][32][y],x*32*y 大约是6~12G。 (x, y 在运行时确定。)

我想了一个办法,就是做char *a=malloc(x*32*y),用*(a+32*y*i+y*j+k)代替a[i][j][k]

但是,与a[i][j][k] 相比,这看起来不太方便。

有没有更好的办法?

添加: 它是a[x][32][datlen],其中datlen 是在运行时确定的,x 是根据内存设置的。

数组中的所有数据都是新的。而且我有 16 或 32GB 内存的数学来运行它。

【问题讨论】:

  • 考虑宏还是内联函数?对于如此庞大的数据集,请考虑使用 mmap 和/或其他增加局部性的技术——这可能不是同一个“平面”数组。
  • a[X][N][Y] 在概念上映射到什么?我敢打赌,您可以使用 BDB、Sqlite 或 HDF5 将数据留在磁盘上,并让您的程序检索适当大小的块。就你的问题而言,我们只是猜测:)

标签: c dynamic multidimensional-array


【解决方案1】:

错误:在引用动态分配的内存时,您应该仍然可以使用 a[i][j][k] 语法。

正确:使用宏至少可以让工作更轻松

#define A(i,j,k) *(a+32*y*i+y*j+k)
A(1,2,3) would then do the right thing.

【讨论】:

  • 这是不可能的,因为尺寸的 size 在编译时是未知的——即使有运行时支持,也不能分配给输入char[x][32][y]。 (除非我只是约会到 C89,这是一个很好的可能性。)
  • @pst:嗯。好点子。它适用于一维数组,但我没有足够仔细地考虑您正在处理的限制。我修改了建议宏的答案。
  • 仍然无法工作,因为宏是固定定义的。您无法在运行时更改 32*y
  • @Zan Lynx:您可以在运行时计算 32*y。宏只提供参数的文本替换。所以 A(1,2,3) 被翻译成 *(a+32*y*1+y*2+3) 并且系统在运行时计算它,就像你在那里写代码一样。它不应该与编译器常量表达式减少混淆(可能发生在宏替换的结果上,但在这种情况下不会发生)。
  • @Seth:假设您决定将数组重新分配为 64 而不是 32?你的宏不起作用。跟踪当前数组维度的数据结构和函数更好。
【解决方案2】:

我怀疑你会找到一个系统会为你分配那么大的连续内存*。您将不得不使用某种分块策略。

您需要问:“您的数据访问模式是什么?”

如果是一些跨步(无论是 1D 还是 2D),使用它来为每个块选择适当的内存分配。使用数据结构来表示每个步幅(可能只是一个包含字符数组的结构)。

编辑:我没有注意到您关于使用a[i][j][k] 语法访问新发现的12G 连续内存块的第二个“问题”。这在我所知道的任何 C 级消费者发行版中都不会发生。

(*) 和 640k 对任何人来说都应该足够了。

【讨论】:

  • 例如,如果您正在访问由char[32][Y] 组成的X 块,则跨X 执行分块。
  • 更好的是,X 块(其中 X 严格大于 32 * Y)可能是一个不错的选择。当且仅当您正在处理 32 * Y 部分,而不是一些奇怪的列排序步幅(a la Fortran)。
  • 我想知道为什么只要空闲内存+交换空间足够,连续内存就是一个问题。我记得 malloc(和所有用户空间指针)将返回一个虚拟地址,Linux 内核将处理物理映射。
  • malloc 并不总是能够这样做,我发现。通常在这些情况下我使用mmap
【解决方案3】:

因为这是 C,所以你不能把所有东西都包装成一个方便的 C++ 对象。

但我会做类似的事情。设计一系列函数来分配、操作和销毁你的这种新数据类型。

要读取或写入一段数据,请调用一个函数。切勿直接接触数据。事实上,如果您可以对数据使用void* 句柄,甚至不将真实数据类型放入包含的头文件中,那是最好的做法。

这样,您可以将函数定义为对一个非常大的内存块、一组大内存块甚至是磁盘上的块数据库进行操作。

既然我写了那句话,让我部分收回它。如果您需要更高的性能,您可能希望将包含的头文件中的所有函数定义为内联定义。这将使您的编译器消除几乎所有的函数调用开销并积极优化。

我承认matrix_set(x, y, z, value) 不如matrix[x][y][z] = value 漂亮,但它也能正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 2022-08-19
    • 2018-05-16
    • 2011-02-16
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    相关资源
    最近更新 更多