【问题标题】:Why does writing to an unrelated file cause the load function to be so slow?为什么写入不相关的文件会导致加载功能如此缓慢?
【发布时间】:2013-03-01 11:34:45
【问题描述】:

我刚刚花了一段时间调试一些特别慢的代码,并完全被 MATLAB 分析器抛弃了。在我看来,这就像一个巨大的错误,所以我想知道是否有人可以对这里发生的事情有所了解。

下面是一些会导致问题的代码:

function profiler_test

  %%% Create 20 files with random data

  count = 20;

  for i = 1 : count
    x = rand(3);
    save(sprintf('temp_file_%06d', i), 'x'); 
  end

  %%% Load them in a for loop

  xs = cell(1, count);

  tic;
  for i = 1 : count
    x = load(sprintf('temp_file_%06d', i), 'x');
    xs{i} = x.x;
  end
  toc

  %%% Load them in a for loop, but writing a small log file on the way

  tic;
  for i = 1 : count
    x = load(sprintf('temp_file_%06d', i), 'x');
    xs{i} = x.x;

    file = fopen(sprintf('temp_logfile_%d', i), 'w');
    fprintf(file, 'Success\n');
    fclose(file);
  end
  toc


end

第一个 for 循环耗时 0.239739 秒,第二个循环耗时 4.411179。

现在,我应该明确表示我知道我的草率想法,如第二个 for 循环示例所示,为每个结果创建一个日志文件 - 这是因为我在一个集群上运行我看不到输出,我想要一个函数进度的廉价指示,结果证明这是瓶颈。我对此很好

然而,我的问题是我花了一天时间尝试优化错误的行,因为 MATLAB 分析器这样说:

         1   24   tic; 
         1   25   for i = 1 : count 
4.41    20   26     x = load(sprintf('temp_file_%06d', i), 'x'); 
        20   27     xs{i} = x.x; 
             28     
        20   29     file = fopen(sprintf('temp_logfile_%d', i), 'w'); 
        20   30     fprintf(file, 'Success\n'); 
        20   31     fclose(file); 
        20   32   end 
         1   33   toc

将执行最后三行所花费的整个时间放在load 的行上。在我的实际程序中,load 并没有那么接近另一个位,所以直到我决定不信任分析器时我才想到它。我的问题是:这里发生了什么?为什么会发生这种情况,我是否应该注意这种更奇怪的行为?

我正在使用 MATLAB 2011a。非常感谢。

编辑:我似乎造成了一些混乱,抱歉。情况如下:

  • 上面显示的两个for 循环是相同的,只是第二个循环在底部有三行,每次迭代都会写入一个临时文件。
  • 第二个循环的运行时间要长得多:结论是最后三行是速度增加的原因。当它们被移除后,代码又很快了。
  • 但是,分析器确实将第二个循环的任何时间归因于最后三个语句。相反,它告诉我我的 load 函数调用 - 与第一个循环完全相同的调用,它更快 - 现在需要 4 秒而不是 0.2 秒。因此,要么最后三行的存在 导致 load 变慢(我忽略了这一点;这甚至有可能吗?),或者 MATLAB 分析器错误地报告 load 是明显不是时需要 4 秒。

无论如何,在我看来,正在发生一些非常奇怪的事情。

编辑:似乎自己回答了,见下文。因误导而更改标题

【问题讨论】:

  • 你是说load 不接受4.41 s 并且Matlab 显示错误?您写道,第一个代码 sn-p 中的第二个 for 循环也采用 4.41 s;循环只是加载数据。
  • 是的,这正是我要说的。抱歉,如果我说得不够清楚:除了第二个循环中的日志记录之外,这两个循环是相同的,但是大量时间增加错误地归因于 load 调用。
  • 我想我对代码中三个循环中的第二个感到困惑。我猜你不算第一个循环
  • 也是真的,又是我的错!无论如何,我似乎已经解决了 - 见下文。

标签: matlab matlab-load


【解决方案1】:

我在您的帖子中没有看到任何错误的证据。

您提到整个循环大约需要 4.111,而分析器显示第 26 行大约需要 4.11

这意味着所有其他行加起来的时间少于0.01,因此每行需要四舍五入的零秒数。

我的猜测是没有打印零,并且您将其解释为其他行没有计时。

我可能遗漏了一些东西,但到目前为止 MATLAB 提供的输出似乎是一致的。

【讨论】:

  • 对不起,我觉得我说得不够清楚;我将对我的问题进行编辑!
  • @jazzbassrob 请测量每行的时间,然后得出结论,添加行后的时间增加实际上发生在这些行中。也许它们只是因为较少的优化或类似原因而减慢了您的负载。
  • 是的,我接受我自动假设额外的时间发生在那些人身上,而不是load实际上放慢了速度,但我的问题仍然存在:为什么?什么样的优化会导致这种情况?
  • 我想我自己已经回答过了,但是谢谢 - 你让我走上了正确的道路!
【解决方案2】:

其实我想我已经解决了。我错误地得出结论,即在新行上发生了额外的处理时间,所以我的问题现在有点误导 - 分析器是正确的。但是,我仍然不明白为什么写入临时文件会导致load 变慢。我有一个想法,就是试试这个:

file = fopen(sprintf('../temp_logfile_%d', i), 'w');

即写入父目录而不是当前工作目录中的文件。这消除了问题,而且速度非常快。我猜的原因是当前目录在我的 MATLAB 搜索路径中,还有一堆其他目录。我假设每次 MATLAB 使用一个查看整个搜索路径的函数时,就像load 所做的那样,它会检查是否有任何目录已被修改,如果是,则重新解析整个文件以查看哪些文件可用。将新文件写入工作目录肯定会导致这种情况。这在我的情况下可能更糟,因为我在工作目录中还有一整棵子目录树,它们是搜索路径的一部分。

无论如何,感谢那些看过的人,很抱歉答案与问题完全不同。使用依赖于整个搜索路径的函数时要注意!

【讨论】:

  • 很好的调试 :) 我很高兴看到了这个问题。
  • +1 良好而详细的解释,尤其是对问题的编辑。
【解决方案3】:

我得到以下由 MATLAB 2012b 的分析器生成的报告,我没有看到错误。

【讨论】:

  • 这很有趣;我的当然不像那样,因为第二个循环需要 4 秒!我确实有 2012a 可用,所以我会尝试比较一下
  • 可能是 I/O 配置差异,而不是 CPU 或版本,可能是由于 jazzbassrob 在连接了非本地存储或网络驱动器的集群上运行? Abhishek 的数字看起来就像您对本地磁盘所期望的那样,所有事情都发生在磁盘缓存中。 jazzbassrob 的数字,即使是更快的 0.239,对于本地磁盘来说也相当慢,更接近于未缓存的 I/O。
猜你喜欢
  • 2021-11-18
  • 1970-01-01
  • 2012-10-04
  • 1970-01-01
  • 2017-09-01
  • 2014-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多