我想定义一个3D数组/指针来存储我的计算结果:
#include <stdio.h>
int main(void) {
float ***ww;
int i, j, k;
int n1 = 3000, n2 = 6000, n3 = 9000;
ww = floatalloc3(n1, n2, n3); /* floatalloc3 is a self-defined function used to allocate memory space for 3D array/pointer */
for (i = 0; i < n1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n3; k++) {
ww[i][j][k] = 0.0;
}
}
}
free(**ww);
free(*ww);
free(ww);
return 0;
}
但cannot allocate 648000000000 bytes: Cannot allocate memory
弹出错误。那我怎么解决这个问题呢?
是否可以拆分数据并将其存储到不同的内核?
答案 0 :(得分:3)
您要分配大约3000 * 6000 * 9000 * 4个字节的数据,即〜 648GB ,有点。
答案 1 :(得分:3)
您试图分配的内存量似乎是巨大的:6,480亿字节加上2个间接级别的开销!您的系统可能不允许您分配那么多的内存。
您应该测试floatalloc3
的返回值以检测分配失败。实际上,发布此自定义函数的源代码以确认其正确性将很有用。
还请注意,这3个free
调用可能不足以释放分配的块,但是如果没有floatalloc3
的源代码,则只能推测。
答案 2 :(得分:2)
如果您确实打算计算3000×6000×9000个浮点值(162,000,000,000个值),则需要重新考虑您的方法。
有几种方法,但是最典型的方法是将任务分成较小的部分,然后逐个计算。
如果网格几乎是空的,但是您需要以不可预测的方式访问它(使分割任务变得不可取),则可以使用特定于OS的方法来对数据集进行内存映射。 (不过,您确实需要一个64位OS来对此特定数据集执行此操作;并且您还需要在某些文件系统上有足够的存储空间来存储数据。)我已在2011年的另一篇Linux中展示了如何做到这一点。论坛here;此示例程序处理了一个TB级的内存映射数据集,几乎是OP正在考虑的数据集大小的两倍。
无论如何,您绝对不希望使用两级间接访问数据。这严重破坏了当前CPU预测和缓存访问的能力,并会导致性能下降。相反,您应该使用线性数据结构。例如:
size_t xsize;
size_t ysize;
size_t zsize;
float *cells;
#define CELL(x,y,z) cells[(x) + xsize*( (y) + ysize * (z) )]
换句话说,网格中每个单元格的索引为(x) + (y)*xsize + (z)*xsize*ysize
。不仅数据然后在内存中是连续的(这对于缓存很重要),而且CPU(和您的编译器)还可以根据访问模式更好地预测将来的访问。