在Matlab中,log(a*b)是否总是比log(a)+log(b)更快?

5

在Matlab中,log(a*b)的速度是否总是快于log(a) + log(b)?

我测试了几组输入数据,似乎log(a*b)更快。您有经验的朋友可以给我提供一些意见吗?也许是警告,这可能并不总是正确的,或者其他需要注意的事项?因此,在第一种情况下,我们有1个对数运算和1个乘法;而在第二种情况下,我们有两个对数运算和一个求和。

编辑:

为了补充我的原始帖子,更一般的问题是:

log(a*b*...*z)是否总是比log(a) + log(b) + ... + log(z)更快?

谢谢


4
我认为对数时间 > 乘法时间 > 加法时间。因此这个观察结果是有意义的。 - lurker
3个回答

13

log(a*b)应该总是更快的,因为计算对数是昂贵的。在log(a*b)中,您只需要计算一次,在log(a)+log(b)中,您需要计算两次。

与对数、指数等相比,计算乘积和求和非常简单。就处理器周期而言,求和和乘积通常都小于5,而指数和对数可以从50到200个周期不等,这取决于一些架构。

log(a*b*...*z)是否总是比log(a) + log(b) + ... + log(z)更快?

是的,绝对是的。尽可能避免计算对数。

这里有一个小实验:

a=rand(5000000,1);

% log(a(1)*a(2)...)
tic
for ii=1:100
    res=log(prod(a));
end
toc
% Elapsed time is 0.649393 seconds.  

% log(a(1))+log(a(2))+...
tic
for ii=1:100
    res=sum(log(a));
end
toc
% Elapsed time is 6.894769 seconds.

在某个时间点,时间比率将会饱和。它的饱和点取决于你的处理器架构,但不同之处至少为一个数量级。


在复杂对数的情况下,差异更加明显,例如 a 是一个复随机值向量。 - horchler
3
注意,将许多在[0,1]范围内的小值相乘会很快变成零。在使用概率时,这种问题经常出现...因此速度并不是一切,当涉及到浮点数时,你还应该关注数值稳定性。请谨慎操作。 - Amro
1
为了说明情况有多糟糕,在您上面的示例中,只有在大约700个元素(500万个元素中)之后,产品才变为零:sum(cumprod(a) > 0)给了我729。 - Amro

9

请注意,虽然计算乘积的对数更快,但由于机器精度问题,有时可能会出现错误。

其中一个问题情况是使用大量整数操作数或大数作为操作数。在这种情况下,乘积 a_1 * a_2 * ... a_n 会导致溢出,而计算对数之和则不会。

另一个问题情况是使用小数,使得它们的乘积由于机器精度而变成零(正如Amro所提到的)。


1
好的,那样的话我们可以创建部分乘积,在溢出之前进行乘法运算,然后取其对数。然后继续做同样的事情,将项累加到乘积中,在溢出之前取对数。同意吗? - user2381422
1
是的,听起来可行。 - Andrey Rubshtein
2
+1 对一个已经有答案的问题进行了很好的观察。 - Werner
@user2381422 不,我来自巴西。我应该在这里说我的糟糕德语吗?我来自巴西(我更喜欢用葡萄牙语写作Brasil,因为它看起来更美)x) - Werner

2
尽管通常做log(a*b)log(a) + log(b)更快,但如果难以评估a*b,这种情况就不成立。在这种情况下,实际上使用第二种方法更快。

例子:

a = 0;
b = Inf;
tic,for t = 1:1e6 log(a*b); end,toc
tic,for t = 1:1e6 log(a)+log(b); end,toc

当然,在这两种情况下,它都会被评估为NaN,但第二种情况比第一种情况快得多。

在现代处理器上,0*Inf 的处理速度很快;这并不是什么“难以评估”的问题。(在过去,一些处理器执行与无穷大和NaN的算术时会遇到停顿,但这已经不再是一个真正的问题了) - Stephen Canon
@StephenCanon 嗯,时间表显示它仍然很慢。也许缓慢的部分是评估 log(NaN) 而不是通过将零乘以无穷大来创建 NaN。当然,慢是相对的,'正常'情况只快约2倍。 - Dennis Jaheruddin
1
当然有可能在您的系统上,log(nan) 的速度比 log(0) 和 log(inf) 慢,但这只是一个数学库实现的怪癖,并不是普遍适用的发现。 - Stephen Canon
1
@StephenCanon 是的,但是这个问题确实有一个matlab标签。 - Dennis Jaheruddin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接