【问题标题】:Optimize run time of octave/matlab function优化octave/matlab函数的运行时间
【发布时间】:2013-08-18 03:47:53
【问题描述】:


我正在使用适用于 Octave 的 Google Earth Toolbox,它与为 MATLAB 制作的同一个库非常相似。有关该工具的 MATLAB 文档,请参阅 this link

不幸的是,我在使用某个功能时遇到了一些问题:ge_quiver。此函数创建一个颤动图并将结果转换为 KML 代码。我的问题 是不是太慢了,我不喜欢。

对于 30x30 大小的数据变量,该函数大约需要 10 秒才能完成。这很好,除了我正在尝试制作一个动画颤动图,还有 23 个其他相同大小的数据变量(总共 24 个)。由于 Octave(以及 MATLAB)通常只在一个线程上运行,因此整个过程是串行运行的,需要 10*24 = 240 秒。

我尝试了parfor 循环,但它们只从总运行时间中删除了 10 秒。我有一台16核的电脑。考虑到这是令人尴尬的并行(变量之间没有依赖关系),理想情况下应该这样:

前 16 个变量需要 10 秒
+ 10 秒剩余 8 个变量
-------------------------------------------------- ----
= 总共 20 秒。

我什至没有测试过arrayfun,因为我不知道如何调整我的功能(p_ge_quiver)。尽管如此,许多人说 arrayfun 不会让它更快。

以下代码大致是我想要做的。记住变量 data_u 的大小为 30x30x24。 data_vlonlat 也是如此。

...
...

[YYYY,MM,DD,HH,mm,ss] = ncdate(NCFILE);
date_s.year   = YYYY;
date_s.month  = MM;
date_s.day    = DD;
date_s.hour   = HH;
date_s.minute = mm;
date_s.second = ss;

TIMESTEP = 60;
parfor i = 1:size(data_u,3)
    dt     = TIMESTEP*i;
    kml(i) = p_ge_quiver(lon,lat,data_u,data_v,dt,TIMESTEP,data_s);
endparfor

...
...

function kml = p_ge_quiver(lon,lat,u,v,data_time,step,date_s)
% V_GE_QUIVER - Writes the quiver plot into KML.

    % Get date variables.
    YYYY = date_s.year;
    MM   = date_s.month;
    DD   = date_s.day;
    HH   = date_s.hour;
    mm   = date_s.minute;
    ss   = date_s.second;

    % Date format. Use Google's.
    F = 'yyyy-mm-ddTHH:MM:SSZ';

    % Start and end dates of data.
    tStart = datestr(datenum(YYYY,MM,DD,HH,mm+data_time,ss),F);
    tEnd   = datestr(datenum(YYYY,MM,DD,HH,mm+data_time+step,ss),F);

    % Quiver plot.
    kml = ge_quiver(lon,lat,u,v,'timeSpanStart', tStart, ...
                                'timeSpanStop' , tEnd  , ...
                                'visibility'   , 0     , ...
                                'lineColor'    , 'AAFFFFFF');



end

【问题讨论】:

  • 如果我错了,请纠正我,但我不认为 parfor 是在 Octave 中实现的(它被解析器识别,但现在只是一个常规的 for-loop)..它在包generaloctave.sourceforge.net/general/overview.html#ParallelComputing中确实有一些并行计算功能。
  • 我也读过这个,但我确实测量了 for 和 parfor 实现之间的 10 秒差异。非常混乱。
  • 我假设(至少在 Matlab 中)您在运行代码之前打开了matlabpool?虽然三个 30×30×24 数组的内存并不多,但谁知道 ge_quiver 在内部内存方面做了什么。

标签: multithreading matlab octave


【解决方案1】:

在我看来,问题在于ge_quiver 在内部做了什么,而你没有展示出来。除此之外,您应该注意,这种语言旨在编写矢量化代码(不仅仅是因为速度上的差异)。

查看您的代码,您可以通过使用矢量化语法来大大简化它(这通常也会影响速度):

step = 60;
dt = step:step:(step * size (data_u, 3));

## Get date variables.
YYYY = date_s.year;
MM   = date_s.month;
DD   = date_s.day;
HH   = date_s.hour;
mm   = date_s.minute;
ss   = date_s.second;

## Date format. Use Google's.
F = "yyyy-mm-ddTHH:MM:SSZ";

tStart = datestr (datenum (YYYY, MM, DD, HH, mm + dt       , ss), F);
tEnd   = datestr (datenum (YYYY, MM, DD, HH, mm + dt + step, ss), F);

此时,tStarttEnd 拥有您需要的所有日期,每行一次。唯一需要的循环如下:

for i=1:rows(tStart)
    kml = ge_quiver (lon, lat, data_u, data_v, "timeSpanStart", tStart(i,:), ...
                                               "timeSpanStop" , tEnd(i,:)  , ...
                                               "visibility"   , 0          , ...
                                               "lineColor"    , "AAFFFFFF");
endfor

此时完全取决于ge_quiver 所做的事情。您链接的 mathworks 站点显示为正在维护中。我查看了 the Google Earth toolbox website 并找不到该函数(虽然他们有一个 ge_quiver3 函数)。

我认为这种语言的函数应该允许向量输入,所以去确认一下。也许你根本不需要循环。

【讨论】:

  • 我很欣赏代码应该被矢量化,但是 ge_quiver 正是我想要矢量化的函数不在您的解决方案中。您的解决方案可能会从我的总运行时间中删除几毫秒,但仅此而已。
  • @jhc 好吧,除非您告诉您更改 ge_quiver 或告诉我们如何使用它,否则没有任何优化可做。您的链接又可以使用了,但我仍然认为那里没有 ge_quiver 功能。
  • 是的,由于某种原因,新工具箱没有 ge_quiver。无论如何,我想做的是在不同的线程中运行每个 ge_quiver,但我根本不知道如何。 parfor 应该有效。
  • @jhc parfor 在 Octave 映射到普通的 for。要走这条路,您最好的选择是openmpi_ext package。查看软件包示例。但实际上,您几乎多次将相同的数据传递给ge_quiver。正确的做法应该是修复ge_quiver。这就是这种语言的设计方式。
猜你喜欢
  • 2016-03-06
  • 2011-07-08
  • 1970-01-01
  • 2015-01-27
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
相关资源
最近更新 更多