从硬盘读取灰度图像的最快方法

The fastest way of reading grayscale image from HDD

我正在使用 GPU (CUDA) 上的图像处理。 CUDA 内核的输入是两个灰度 8 位图像 (.tif)。它们必须在 GPU RAM 内存中作为一维数组(从 0 开始,行优先存储)。处理时间约为 24 毫秒,因此阅读速度对我来说很重要。为此,首先我需要将图像从 HDD 读取到 CPU RAM 内存(进入一维浮点数组),然后使用 cudamemcpy 将其复制到 GPU RAM 中。使用 C++ 从 HDD 读取最快的方法是什么?

我的图像是 8 位灰度 1200x1600(大小 1.92 mb)。我写了测试程序,它读取了大约 250 张图像并测量了时间:

使用 matlab (imread) 读取 1 张图像的时间是 5.8ms。这对应于 ~300 Mb/s 并且接近我硬盘的峰值带宽。

但是,只要我使用 CUDA,我就需要使用 C++。我安装了 OpenCV。不幸的是,我无法使用 OpenCV 将图像直接读入浮点数组。将其读入 uchar 数组后,我将数据转换为浮点数数组:

image = imread(b, 0);
image.convertTo(img_float, CV_32F);
float *d = img_float.ptr<float>(0);

测试此实现后,我得到了更糟糕的结果:每个图像 8.8ms。没有转换它是 8.2 ms。通常 c++ 更快,然后是 Matlab。是否有可能像我使用 Matlab 那样使用 C++ 实现峰值带宽?

P.S。在 C++ 中,我使用 release x64 模式进行了全面优化。读取 250 张不同图像的时间是通过 c++ 中的函数 clock() 和 matlab 中的 tic-toc 测量的(并且被划分为 250 多个以查找每张图像的时间)。

谢谢

有几点要看。第一:尝试验证您的基准测试是否真的正确。文件系统缓存会影响结果吗?如果是,请尝试使用更大的数据大小。您的基准测试是否衡量了您真正想要衡量的内容(即,MatLab 是否真的将图像转换为浮点数)?图片读取正确无误吗?

您的问题 "What is the fastest way to read from HDD with c++?" 的直接答案可能是 "C++ has (almost) no impact on speed of data transfer from HDD to RAM"。分配所需的内存量并使用 OS 的本机 API 读取文件:您将获得最大值。

也许重要的是 TIFF 图像处理库。尝试找出 OpenCV 使用什么库来处理 TIFF。它是否执行任何不必要的转换为某种中间表示或只是读取字节块?如果是前者,尝试寻找其他库甚至手动解析TIFF图像(如果不是压缩的,解析TIFF没什么大不了的)。转换为 float 可能不是瓶颈。 OpenCV 能够使用多线程(验证是否利用了所有 CPU 核心)和矢量化(您可以检查这一点,也许通过查看执行转换的实际代码)。此外,如果您需要重复执行这些操作,请避免在循环中分配和释放内存:不要执行转换 "in-place",而是使用两个单独的数组(一个用于 8 位图像,一个用于浮点数) .

P.S。不是可以在GPU中转换图像吗?