gpt4 book ai didi

c++ - 一次 I/O 执行速度比一次读取一点慢

转载 作者:行者123 更新时间:2023-11-30 04:36:10 28 4
gpt4 key购买 nike

我正在研究我们准备使用 cuda 放在 GPU 上的优化和算法。

I/O 部分从 3 个不同的图像中读入,一次一行。这正好在对图像运行过滤器的循环中间。我决定尝试预先加载通过将 I/O 移除到它自己的循环中而生成的值,并将这些值转储到保存图像的数组中,并用于计算。

现在的问题是,我的应用程序似乎在缓冲区满载数据时运行速度较慢,而在每次迭代都必须出到磁盘以获取新数据时运行速度更快。

这可能是什么原因造成的?较大缓冲区的缓存未命中真的会降低性能吗?这不是内存问题——这台机器上有 24GB 内存,它有足够的内存。

不确定还能是什么,愿意听取想法

最佳答案

@Derek 提供了以下附加信息:

(Run time) ... "is over a minute, compared to 10 - 14 seconds before. I am not doing any specific threading, though I do have some OpenMP pragmas. Moving the I/O outside of the filter loop did not change any of those though. I am running CentOS 5.5. The image size is approx 72MB"

这是运行时间的巨大差异。由于使用了 OpenMP,我们可以假设有多个线程。由于您只处理 72MB 的数据,我看不出 I/O 时间的差异有多大。我们可以肯定读取时间比您原来的 10-14 秒要短,因此除非您在代码的那部分有错误,否则额外的时间在过滤器部分。这些图像大概是二进制的?正如@Satya 所建议的那样,分析您的代码或至少添加一些计时打印输出可能有助于确定问题所在。

在循环中读取的“优势”可能是:

  1. 操作系统为您提供了一些并行性,因为它能够与您的计算并行执行一些 I/O,例如提前阅读。当你提前阅读所有内容时,你就失去了那种并行性,在阅读时有效地阻塞。
  2. 当您的过滤器访问数据时,读取的数据在缓存中。如果处理相对于内存带宽而言是轻量级的,那么缓存未命中确实会降低性能。很难相信这会在此用例中产生重大差异,因为磁盘 I/O 比内存慢得多。

鉴于您的最新更新,我们似乎更有可能处理#2。需要注意的是内存访问模式(包括所有线程),您可能会看到缓存抖动,因为过去在主内存中相邻的数据现在分开得更远。这可能会产生很大的影响,因为如果您有很多内存访问并且它们都是缓存未命中,您总是会承担进一步访问数据的成本,这可能是一个数量级的差异。

解决这个问题的方法是将你的内存排列成 strip 状,例如第一张图片的 n 行,第二张图片的 n 行,第三张图片的 n 行。 IIRC 这种技术称为“ strip 化”。确切的 strip 大小取决于您的 CPU,但您可以对其进行试验(如果足够大,也可以从与内循环读取的相同数据量开始)。

例如:

stripe_number = 0;
do
{
count = fread(striped_buffer+(STRIPE_SIZE*stripe_number*NUM_IMAGES), 1, STRIPE_SIZE, image_file);
stripe_number++;
} while(count != 0);

一次读取一个文件,这样您就不会在驱动器上来回搜索。

无论如何,为了最大限度地提高性能,您可能需要考虑使用异步/重叠 I/O,以便在处理前一位图像数据的同时接收下一位图像数据。

如果您在 Windows 下进行开发,这可以让您开始执行重叠 I/O: http://msdn.microsoft.com/en-us/library/ms686358%28v=vs.85%29.aspx

并行执行 I/O 后,您可以确定瓶颈是在 I/O 中还是在处理中。有不同的技术可以优化它们。

关于c++ - 一次 I/O 执行速度比一次读取一点慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4742523/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com