快速启动3d数组的方法(C ++)

时间:2017-10-24 14:05:57

标签: c++ performance multidimensional-array memory-management

在我的程序中,我需要创建一个大的3d数组(~1GB) 我目前正在使用两个for循环来初始化数组:

float*** array = new float** [m_width];

for (unsigned int i = 0; i < m_width; i++)
{
    array3d[i] = new float * [m_height];
    for (unsigned int j = 0; j < m_height; j++)
    {
        array3d[i][j] = new float[m_layers];
    }
}

代码工作正常,但速度很慢。 所以我的问题是:是否有更快的方法来初始化/保留多维数组的内存? (几乎可以立即创建1d阵列)

4 个答案:

答案 0 :(得分:4)

您没有创建3D阵列。您正在创建一个指针数组,每个指针都指向一个指针数组,每个指针都指向float的1D数组。这在分配效率,缓存局部性,访问效率等方面完全不同。

如果您只创建一个大小为width * height * depth的数组,并使用索引算法来访问它,那么效率会更高。并记住拼写的标准方式&#34;动态数组&#34;在C ++中是std::vector;这对您尤其重要,因为vector值初始化其所有元素(float表示将它们初始化为.0f)。你可以轻松地创建这样的东西:

class Array3d
{
  size_t height, depth;
  std::vector<float> data;

public:
  Array3d(size_t width, size_t height, size_t depth) :
    height(height),
    depth(depth),
    data(width * height * depth)
  {}

  float& at(size_t x, size_t y, size_t z)
  { return data[x * height * depth + y * depth + z]; }

  float at(size_t x, size_t y, size_t z) const
  { return data[x * height * depth + y * depth + z]; }
};

添加更多功能,安全检查等。

这个原因要快得多:

  • 在分配时:这只是对(相当昂贵的)动态分配机制的一次调用,而不是问题中的width * height + height + 1次调用。

  • On access:这需要一些整数操作和一个指针取消引用来获取任何数据成员。单独的数组机制需要3个连续的内存提取(计算和偏移,在那里检索指针,偏移它,检索另一个指针,......)。

答案 1 :(得分:2)

从C ++ 11开始,您可以使用以下代码:

library(maps) 
library(geosphere)
library(mapproj)

#load data
locations <- read.csv("articles-authors-locations.csv", header=TRUE, check.names = FALSE)

#plot map with Mollweide projection
myProj.type<-"mollweide"
myProj.orient<-c(90,0,0)
x<-map(proj=myProj.type,orient=myProj.orient,wrap=T,fill=TRUE, col="white", bg="lightblue",xlim=range(locations$ArticleLong),ylim=range(locations$ArticleLat)
       ) 

#plot jittered points for authors' locations
myStartP<-mapproject(jitter(locations$AuthorLong,amount=3),jitter(locations$AuthorLat, amount=1),proj=myProj.type,orient=myProj.orient)
points(myStartP,col="darkblue",pch=20,cex=1)

#set transparent colors
myTColour<-rgb(0,0,0,50,maxColorValue=255)
red_transp <- adjustcolor("red", alpha.f = 0.4) 

#plot lines and jittered points, connecting authors' and articles locations
for (i in 1:nrow(locations))
{
myGC1<-gcIntermediate(c(locations$AuthorLong[i],locations$AuthorLat[i]),c(locations$ArticleLong[i],locations$ArticleLat[i]),addStartEnd=T, n=50)
moll<-mapproject(myGC1[,1],myGC1[,2],projection=myProj.type,orientation=myProj.orient) 
lines(moll$x,moll$y,lwd=2.5,col=myTColour)
myDestP<-mapproject(
  jitter(locations$ArticleLong[i], amount=3),
  jitter(locations$ArticleLat[i], amount=1),
  proj=myProj.type,orient=myProj.orient)
points(myDestP,col=red_transp,pch=20,cex=1)
}

这将创建一个包含填充零的125个整数的3d数组。 恕我直言,这是在堆栈上创建和初始化3d数组的最快(就代码行而言)的方式。

要在堆上创建一个(使用new),其他答案似乎都很好。

当然,你必须在之后填写你的数据,这需要一些时间,但它应该是快速的。

答案 2 :(得分:1)

当我想避免多维数组初始化但想要多维数组访问时,我正在做的一种方法是:

#define IDX_3D(x, y, z, width, height) ((x) + (y) * (width) + (z) * (width) * (height))

void main()
{
    int width, height, depth;
    width = height = depth = 2;
    float* multi_array = new float[width * height * depth];

    multi_array[IDX_3D(1, 1, 1, width, height)] = 1.0f;
}

答案 3 :(得分:0)

我认为有两种选择:

  1. 加载具有数组结构的文件。
  2. 使用线程进行初始化,此表单可以在初始化时使用更多cpu。
  3. 问候。