2

我正在处理 3D 体积图像,可能很大 (256x256x256)。我有 3 本书想要阅读和操作。目前,每卷都存储为一个数字文本文件,我使用ifstream. 我将它保存为一个矩阵(这是我通过动态分配 3D 数组编写的一个类)。然后我对这 3 个矩阵进行运算,加法、乘法甚至傅里叶变换。到目前为止,一切都运行良好,但是,它需要大量的时间,尤其是傅里叶变换,因为它有 6 个嵌套循环。

我想知道如何加快速度。此外,我将图像存储在文本文件中这一事实是否有所不同。我应该将它们保存为二进制文件还是其他更容易/更快的格式读取?是fstream最快的阅读方式吗?我每次都使用相同的 3 个矩阵而不更改它们。这有什么区别吗?另外,指向指针的指针是存储 3D 体积的最佳方式吗?如果不是我还能做什么?

4

4 回答 4

4

此外,指向指针的指针是存储 3d 卷的最佳方式吗?

不,那通常是非常低效的。

如果不是我还能做什么?

如果将其存储在一个连续的块中,并在块中使用计算出的偏移量,您可能会获得更好的性能。

我通常会使用这样的结构:

class DataBlock {

  unsigned int nx;
  unsigned int ny;
  unsigned int nz;
  std::vector<double> data;

  DataBlock(in_nx,in_ny,in_nz) : 
   nx(in_nx), ny(in_ny), nz(in_nz) , data(in_nx*in_ny*in_nz, 0)
  {}

  //You may want to make this check bounds in debug builds
  double& at(unsigned int x, unsigned int y, unsigned int z) { 
    return data[ x + y*nx + z*nx*ny ];
  };

  const double& at(unsigned int x, unsigned int y, unsigned int z) const { 
    return data[ x + y*nx + z*nx*ny ];
  };

  private:
    //Dont want this class copied, so remove the copy constructor and assignment.
    DataBlock(const DataBlock&);
    DataBlock&operator=(const DataBlock&);
};
于 2013-05-17T08:07:54.783 回答
3

将大型(256个 3元素)3D 图像文件存储为纯文本是一种资源浪费。

不失一般性,如果您的图像有一个纯文本文件,并且文件的每一行包含一个值,您将不得不读取几个字符,直到找到行尾(对于 3 位数字,这些将是 4 个字节;3 个字节用于数字,1 个字节用于换行符)。之后,您必须将这些个位数转换为数字。使用二进制时,您直接读取固定数量的字节,您将获得您的数字。您可以并且应该将其作为二进制图像写入和读取。

这样做有几种格式,我推荐的一种是 VTK 的元图像文件格式。在这种格式中,您有一个纯文本头文件和一个包含实际图像数据的二进制文件。通过头文件中的信息,您将知道图像有多大以及您将使用什么数据类型。在您的程序中,您可以直接读取二进制数据并将其保存到 3D 数组中。

如果您真的想加快速度,请使用 CUDA 或 OpenCL,这对您的应用程序来说非常快。

有几个 C++ 库可以帮助您编写、保存和操作图像数据,包括前面提到的 VTK 和 ITK。

于 2013-05-17T08:22:14.713 回答
1

256 3是一个相当大的数字。解析 256 3 个文本字符串将花费大量时间。使用二进制将使读/写过程更快,因为它不需要将数字转换为字符串/从字符串转换,并且使用更少的空间。例如,char要从文本文件中读取数字 123,程序需要将其作为字符串读取,并使用大量乘以 10 将十进制转换为二进制。而如果您直接将其写为二进制值,则0b01111011只需将该字节再次读回内存,根本没有转换。

使用十六进制数字也可以提高读取速度,因为每个十六进制数字都可以直接映射到二进制值,但是如果您需要更高的速度,二进制文件是可行的方法。只需一个命令即可在不到 1 秒fread的时间内将整个 256个 3字节 = 16MB 的文件加载到内存中。完成后,只需fwrite将其返回文件即可。为了加快速度,您可以使用 SIMD (SSE/AVX)、CUDA 或其他并行处理技术。您可以通过多线程或仅保存非零值来进一步提高速度,因为在许多情况下,大多数值通常为 0。

另一个原因可能是因为您的数组很大,并且每个维度都是 2 的幂。这已在许多关于 SO 的问题中讨论过:

您可以考虑将最后一个维度更改为 257 并重试。或者更好地使用另一种算法,例如对缓存更友好的分而治之

于 2013-05-18T08:17:07.273 回答
0

您应该在负载和进程周围添加计时器,以便知道哪个花费的时间最多,并将优化工作重点放在它上面。如果您控制文件格式,请制作一种更易于阅读的格式。如果是处理,我会附和前人所说的,研究高效的内存布局以及 GPGPU 计算。祝你好运。

于 2013-05-18T13:18:05.210 回答