繁体   English   中英

初始化 3d 数组的快速方法 (C++)

[英]Fast way of initallizing a 3d array (C++)

在我的程序中,我需要创建一个大型 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];
    }
}

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

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

如果您只创建一个大小width * height * depth数组,并使用索引算法来访问它,效率会更高。 请记住,在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调用。

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

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

int array[5][5][5] = {0};

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

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

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

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

#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;
}

我认为有两种选择:

  1. 加载具有数组结构的文件。
  2. 使用Threads初始化,这个表单可以在初始化时使用更多的cpu。

问候。

正如另一个答案所说,这不是一个“块”数组,而是一堆指向分配内存指针的分配指针。 您花费大量时间 (N^2) 分配元素,并花费大量时间分配指针数组。 这是您为拥有不同大小的“行”自由而付出的代价,但这显然是您首先不需要的。

有一篇关于它的著名文章Dynamic Arrays in C—The Wrong Way

正如另一个答案所说,您需要分配一个内存块并大步访问它。

一个明智的选择是使用一个为你做这件事的库。 那里有很多库,一个是Multi (免责声明,我是作者)。

您的代码将减少为:

multi::array<float, 3> arr({m_width, m_height, m_layers});

(添加一个值作为最后一个参数以初始化为定义明确的值。)

幸运的是,您仍然可以使用与代码相同的语法访问元素,例如arr[1][2][3]

完整代码: https ://godbolt.org/z/fT1E7YbPG

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM