【问题标题】:Searching in a vector is too computationally expensive在向量中搜索计算量太大
【发布时间】:2012-03-13 09:37:48
【问题描述】:

我需要执行如下代码块:

x = some_number;
y = some_other_number;

u = a_vector_of_numbers;
v = another_vector_of_numbers;
% u and v are of equal size

r1 = ((x == u) | (x == v));   % Expensive!
r2 = ((y == u) | (y == v));   % Expensive!

q = any(r1 & r2);

您可以将其视为:xy 是图上的两个节点,除非我弄错了,否则这会检查 xy 是否使用邻接列表 [r1, r2] 连接。换句话说,我试图回答这个问题:“是否有这样一个索引i 可以在r1(i)r2(i) 找到xy?”

我需要反复这样做。 r1r2 都可能包含多达数千个唯一值(图中的节点数约为 104),它们的长度为数十万( 106) 的顺序。

我的分析器告诉我,我用 cmets 指示的两行消耗了 99% 的运行时间,而且我的程序需要很长时间才能运行,所以我想知道:这还能优化多少?最小计算时间的基本限制是什么,我离它有多近?

此外,将此特定代码外包给另一种语言也很容易。这样做能带来显着的性能提升吗?

【问题讨论】:

  • 这样的i 可以有多个吗?如果是这样,您需要全部还是只需要第一个/最后一个?
  • 理论上,我的数据中不应该有多个这样的i,因为我的图表是无向的。在实践中,数据有时是脏的。无论如何,我什至不需要第一个或最后一个——我只想知道这样的i 是否存在。但是,如果您的答案依赖于它,则可以对r1/r2 进行一些预处理,并保证对于任何给定的x-y 对,这样的i 永远不会被发现超过一次.

标签: database matlab search optimization


【解决方案1】:

如果您的第一次检查 (r1) 可能会删除大部分结果,则可以预先过滤您的第二次检查以仅检查可能的匹配项。代码如下所示:

mask_r1 = ((x == u) | (x == v));   % Expensive!
r2 = ((y == u(mask_r1)) | (y == v(mask_r1)));   % Less expensive!
q = any(r2);

我什至见过一些案例(通常在旧版本的 Matlab 中),在第一行添加 find 可以提高性能。但我认为不再是这样了(他们已经将优化拉到解析器中。)三种方法的一些计时结果(原始,使用逻辑掩码,使用显式索引列表)如下:

x = 2;
y = 3;
v = randi(200,1e5,1);
u = randi(200,1e5,1);

tic;
for ix = 1:1000
    r1 = ((x == u) | (x == v));   % Expensive!
    r2 = ((y == u) | (y == v));   % Expensive!
    q = any(r1 & r2);
end
toc;  %1.175234


tic;
for ix = 1:1000
    mask_r1 = ((x == u) | (x == v));   % Expensive!
    r2 = ((y == u(mask_r1)) | (y == v(mask_r1)));   % Less expensive!
    q = any(r2);
end
toc;  %0.878857

tic;
for ix = 1:1000
    ixs_r1 = find(((x == u) | (x == v)));   % Expensive!
    r2 = ((y == u(r1)) | (y == v(r1)));   % Less expensive!
    q = any(r2);
end
toc;  %1.118103

【讨论】:

  • 我认为在最好的情况下,这最多可以将我需要的时间减半。我对运行时间的数量级减少更感兴趣。不过,这仍然是一个好主意,对我很有帮助,谢谢!
【解决方案2】:

这个建议我没有测试过,太费力去设置一些真实的测试数据,但是……

您是否尝试过为图形创建邻接矩阵并将其用于查询?虽然创建矩阵(一次)将是一项相对昂贵的操作,但检查是否存在边会比读取两个邻接列表便宜得多(我认为)。

如果您坚持使用当前的算法(或者更确切地说,使用当前的数据结构),如果您仅通过将工作卸载到另一种语言的实现来获得很大的加速,我会感到惊讶。使用另一种语言并不会改变您正在阅读长向量数据以寻找值的事实。

【讨论】:

  • 我会尽量让你知道我实现这个之后会发生什么。
  • 使用我的真实数据,我能够将运行时间从 18 分钟减少到大约 0.3 分钟。谢谢!
  • 空间与时间权衡的好例子。
  • 我忘了建议考虑使用稀疏矩阵作为邻接矩阵。不确定这将如何影响执行时间。
猜你喜欢
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 2021-06-16
  • 2014-09-13
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
相关资源
最近更新 更多