Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 大型三维阵列的动态分配_C_Multidimensional Array - Fatal编程技术网

C 大型三维阵列的动态分配

C 大型三维阵列的动态分配,c,multidimensional-array,C,Multidimensional Array,我正在做一个项目,我需要创建一个三维阵列,一些二维和一维阵列。3D阵列表示空间中的离散坐标,我需要很多点来解决我的问题。阵列大小约为2000*2000*2000。我需要在这些数组中存储“double”值。有人能提出一个有效的方案来实现这一点吗 提前谢谢 /*********************************************************** * Copyright Univ. of Texas M.D. Anderson Cancer Center * 1

我正在做一个项目,我需要创建一个三维阵列,一些二维和一维阵列。3D阵列表示空间中的离散坐标,我需要很多点来解决我的问题。阵列大小约为2000*2000*2000。我需要在这些数组中存储“double”值。有人能提出一个有效的方案来实现这一点吗

提前谢谢

/***********************************************************
 *  Copyright Univ. of Texas M.D. Anderson Cancer Center
 *  1992.
 *
 *  Some routines modified from Numerical Recipes in C,
 *  including error report, array or matrix declaration
 *  and releasing.
 ****/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h>

/***********************************************************
 *  Report error message to stderr, then exit the program
 *  with signal 1.
 ****/
void nrerror(char error_text[])

{
  fprintf(stderr,"%s\n",error_text);
  fprintf(stderr,"...now exiting to system...\n");
  exit(1);
}

/***********************************************************
 *  Allocate an array with index from nl to nh inclusive.
 *
 *  Original matrix and vector from Numerical Recipes in C
 *  don't initialize the elements to zero. This will
 *  be accomplished by the following functions.
 ****/
double *AllocVector(short nl, short nh)
{
  double *v;
  short i;

  v=(double *)malloc((unsigned) (nh-nl+1)*sizeof(double));
  if (!v) nrerror("allocation failure in vector()");

  v -= nl;
  for(i=nl;i<=nh;i++) v[i] = 0.0;   /* init. */
  return v;
}

/***********************************************************
 *  Allocate a matrix with row index from nrl to nrh
 *  inclusive, and column index from ncl to nch
 *  inclusive.
 ****/
double **AllocMatrix(short nrl,short nrh,
                     short ncl,short nch)
{
  short i,j;
  double **m;

  m=(double **) malloc((unsigned) (nrh-nrl+1)
                        *sizeof(double*));
  if (!m) nrerror("allocation failure 1 in matrix()");
  m -= nrl;

  for(i=nrl;i<=nrh;i++) {
    m[i]=(double *) malloc((unsigned) (nch-ncl+1)
                        *sizeof(double));
    if (!m[i]) nrerror("allocation failure 2 in matrix()");
    m[i] -= ncl;
  }

  for(i=nrl;i<=nrh;i++)
    for(j=ncl;j<=nch;j++) m[i][j] = 0.0;
  return m;
}

/***********************************************************
 *  Allocate a 3D array with x index from nxl to nxh
 *  inclusive, y index from nyl to nyh and z index from nzl to nzh
 *  inclusive.
 ****/
double ***Alloc3D(short nxl,short nxh,
                     short nyl,short nyh,
                         short nzl, short nzh)
{
  double ***t;
  short i,j,k;


  t=(double ***) malloc((unsigned) (nxh-nxl+1)*sizeof(double **));
  if (!t) nrerror("allocation failure 1 in matrix()");
  t -= nxl;

  for(i=nxl;i<=nxh;i++) {
    t[i]=(double **) malloc((unsigned) (nyh-nyl+1)*sizeof(double *));
    if (!t[i]) nrerror("allocation failure 2 in matrix()");
    t[i] -= nyl;
    for(j=nyl;j<=nyh;j++) {
         t[i][j]=(double *) malloc((unsigned) (nzh-nzl+1)*sizeof(double));
         if (!t[i][j]) nrerror("allocation failure 3 in matrix()");
         t[i][j] -= nzl;}

  }

  for(i=nxl;i<=nxh;i++)
    for(j=nyl;j<=nyh;j++)
       for(k=nzl; k<=nzh;k++) t[i][j][k] = 0.0;
  return t;
}
/***********************************************************
 *Index to 3D array.
 ****/
long index(int x, int y, int z, int Size)
{
     return (Size*Size*x + Size*y + z);
}
/***********************************************************
 *  Release the memory.
 ****/
void FreeVector(double *v,short nl,short nh)
{
  free((char*) (v+nl));
}

/***********************************************************
 *  Release the memory.
 ****/
void FreeMatrix(double **m,short nrl,short nrh,
                short ncl,short nch)
{
  short i;

  for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
  free((char*) (m+nrl));
}


/***********************************************************
 *  Release the memory.
 ****/
void Free3D(double ***t,short nxl,short nxh,
                short nyl,short nyh, short nzl, short nzh)
{
  short i,j;

  for(i=nxh;i>=nxl;i--)
   {for(j=nyl;j>=nyl;j--) free((char*) (t[i][j]+nzl));
    free((char*) (t[i]+nyl));
   }
  free((char*) (t+nxl));
}

***********************************************************************************

void InitOutputData(InputStruct In_Parm, OutStruct * Out_Ptr)
{
  short nz = In_Parm.nz;
  short nr = In_Parm.nr;
  short na = In_Parm.na;
  short nl = In_Parm.num_layers;
  short size = nr/2*nr/2*nz;
  /* remember to use nl+2 because of 2 for ambient. */

  if(nz<=0 || nr<=0 || na<=0 || nl<=0)
    nrerror("Wrong grid parameters.\n");

  /* Init pure numbers. */
  Out_Ptr->Rsp = 0.0;
  Out_Ptr->Rd  = 0.0;
  Out_Ptr->A   = 0.0;
  Out_Ptr->Tt  = 0.0;

  /* Allocate the arrays and the matrices. */
  //Out_Ptr->Rd_ra = AllocMatrix(0,nr-1,0,na-1);
  //Out_Ptr->Rd_r  = AllocVector(0,nr-1);
  //Out_Ptr->Rd_a  = AllocVector(0,na-1);

  Out_Ptr->A_xyz1 = AllocVector(0,size-1);
  Out_Ptr->A_xyz2 = AllocVector(0,size-1);
  Out_Ptr->A_xyz3 = AllocVector(0,size-1);
  Out_Ptr->A_xyz4 = AllocVector(0,size-1);
  Out_Ptr->A_xz  = AllocMatrix(0,nr-1,0,nz-1);
  Out_Ptr->A_z   = AllocVector(0,nz-1);
  Out_Ptr->A_l   = AllocVector(0,nl+1);

  Out_Ptr->Tt_ra = AllocMatrix(0,nr-1,0,na-1);
  Out_Ptr->Tt_r  = AllocVector(0,nr-1);
  Out_Ptr->Tt_a  = AllocVector(0,na-1);
}
/***********************************************************
*德克萨斯大学安德森癌症中心版权所有
*  1992.
*
*从C中的数字公式修改的一些例程,
*包括错误报告、数组或矩阵声明
*然后释放。
****/
#包括
#包括
#包括
#包括
/***********************************************************
*向stderr报告错误消息,然后退出程序
*有信号1。
****/
无效nError(字符错误\u文本[])
{
fprintf(标准,“%s\n”,错误\u文本);
fprintf(stderr,“…正在退出系统…\n”);
出口(1);
}
/***********************************************************
*分配索引从nl到nh(含nl)的数组。
*
*C中数值公式的原始矩阵和向量
*不要将元素初始化为零。这将
*可通过以下功能完成。
****/
双*AllocVector(短nl,短nh)
{
双*v;
短i;
v=(双*)malloc((未签名)(nh nl+1)*sizeof(双));
如果(!v)nError(“向量()中的分配失败”);
v-=nl;
对于(i=nl;iA_xyz3=AllocVector(0,尺寸-1);
Out_Ptr->A_xyz4=AllocVector(0,大小为1);
Out_Ptr->A_xz=AllocMatrix(0,nr-1,0,nz-1);
Out_Ptr->A_z=AllocVector(0,nz-1);
Out_Ptr->A_l=AllocVector(0,nl+1);
Out_Ptr->Tt_ra=AllocMatrix(0,nr-1,0,na-1);
Out_Ptr->Tt_r=AllocVector(0,nr-1);
Out_Ptr->Tt_a=AllocVector(0,na-1);
}
上面是分配数组的代码和调用它们的函数。当大小超过大约7000时,失败的调用是'Out_Ptr->A_xyz1=AllocVector(0,size-1);'。

如果它们是固定大小(或至少是固定的最大大小)在运行时,如果它们比物理RAM大,那么您也可以使用内存映射文件。访问速度至少与RAM+swap一样快,您可以免费将数据序列化到磁盘。您还可以映射总体上大于您的地址空间的映射文件的区域(即窗口)视图


如果你需要大量的细胞,因为你需要一些区域的高细节,但不是均匀的,你可以考虑八叉树。然后你可以在某些部分存储渐进的精细分辨率,你可以重新排序以优化对3D附近区域的访问-这在CFD或医学成像方面非常普遍。这是一个完美的mmap使用案例!您的阵列是64 GB-太大了,无法一次装入RAM。幸运的是,我们可以强制内核为我们完成所有繁重的工作

以下是一些(公认未经测试的)代码:

#包括
#包括
#包括
#包括
#包括
#包括
#定义数组大小((关闭)2000*2000*2000*8)
静态内联off_t idx(off_t x、off_t y、off_t z)
{
返回2000*2000*x+2000*y+z;
}
int main()
{
int fd=open(“my_-mage_-array.dat”,O_-RDWR | O|u-CREAT | O|u-TRUNC);
//我们必须写入文件的末尾,以便正确设置大小。
lseek(fd,数组大小-1,搜索集);
写(fd,“,1);
double*my_-mage_-array=mmap(NULL,数组大小,保护读取,保护写入,映射共享,fd,0);
//现在玩阵列!
my_巨型_数组[idx(4,7,9)]=12;
my_-Great_array[idx(0,0,0)]=my_-Great_array[idx(4,7,9)]*2;
//把它关起来,别漏了你的fd!
munmap(我的大数组,数组大小);
关闭(fd);
移除(“my_-ground_-array.dat”);
返回0;
}

它将是一个稀疏数组吗?坐标是否表示一个规则的网格?即,您必须存储值,或者在需要时可以从一个矩形范围内的网格间距计算值?您需要以顺序或随机访问的方式访问数组吗?您可以存储一个大文件的部分以存储值。不能进行随机访问尽管如此,还是要访问。不要用自动作用域声明,即在函数中声明。堆栈溢出会发生。您是否意识到您正在尝试分配2000x2000x2000x8=64 GB?难怪内存不足!malloc无法分配如此大的块。我从未使用过mmap()。让我试着回答一下。非常感谢。pitc,如果你在32位平台上,2000^3比地址空间大,因此你要么单独处理平面/行/列,要么使用映射视图,要么切换到64位!是的,我得到了这一部分,但我甚至无法使用malloc()分配100*100*100数组.现在,我认为问题不在于malloc。我将把我的代码添加到文章中。问题在于malloc需要一个这么大的未中断内存块!您需要对每个2d平面(甚至可能是每一行)进行malloc分别创建一个数组。这样maloc就可以为100x100块内存找到空间。我也尝试过这样做。看看Alloc 3D。当我尝试使用该函数时也会遇到同样的问题。如果我需要将映射保持打开直到代码结束怎么办。现在的运行时间大约是50小时。可以吗?或者我需要关闭它并在每次写入时打开它。你知道吗可以随时关闭它。50小时就可以了。内核管理所有内存->磁盘活动,我假设是LRU缓存。@pitc-mmap的另一个优点是,每隔10-15分钟将其刷新到磁盘,并序列化您需要的任何其他数据值。然后,如果出现故障,您可以编写代码,从保存的指针恢复如果我想从另一个函数调用创建过程,在其他函数通过指针向映射添加数据时保持映射活动,然后使用另一个函数关闭映射,那么如何创建映射?
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#define ARRAY_SIZE ((off_t)2000*2000*2000*8)

static inline off_t idx(off_t x, off_t y, off_t z)
{
    return 2000*2000*x + 2000*y + z;
}

int main()
{
    int fd = open("my_huge_array.dat", O_RDWR | O_CREAT | O_TRUNC);

    // We have to write to the end of the file for the size to be set properly.
    lseek(fd, ARRAY_SIZE - 1, SEEK_SET);
    write(fd, "", 1);

    double* my_huge_array = mmap(NULL, ARRAY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    // Now play with the array!
    my_huge_array[idx(4, 7, 9)] = 12;
    my_huge_array[idx(0, 0, 0)] = my_huge_array[idx(4, 7, 9)] * 2;

    // Close it up. Don't leak your fd's!
    munmap(my_huge_array, ARRAY_SIZE);
    close(fd);
    remove("my_huge_array.dat");
    return 0;
}