【问题标题】:Optimizing MATLAB code优化 MATLAB 代码
【发布时间】:2011-11-30 04:47:39
【问题描述】:

此代码需要很长时间才能运行(超过 10 分钟)。有什么方法可以优化它,使其在不到一分钟的时间内完成?

clear all;
for i = 1:1000000
    harmonicsum = 0;
    lhs = 0;
    for j = 1:i
        % compute harmonic sum
        harmonicsum = harmonicsum + 1/j;
        % find sum of factors
        if (mod(i,j)==0)
            lhs = lhs + j;
        end
    end
    %define right hand side (rhs) of Riemann Hypothesis
    rhs = harmonicsum + log(harmonicsum) * exp(harmonicsum);

    if lhs > rhs
        disp('Hypothesis violated')
    end
end

【问题讨论】:

  • 关键不是问“N的因数是什么”,而是“有哪些数有j作为因数”,这样容易多了。

标签: performance matlab vectorization


【解决方案1】:

内部循环执行大约 1000000*(1000000+1)/2 = 500000500000 次!难怪它很慢。也许你应该尝试不同的近似方法。

【讨论】:

  • 我不知道如何在不使用双循环的情况下测试因子并测试 1,000,000 个数字中的每一个。
【解决方案2】:

向量化您的算法,我可以将执行时间略微减少到约 8.5 分钟。在一个语句中计算所有谐波和:

Harmonicsum = cumsum(1 ./ (1:1e6));

您现在可以在一个语句中计算右侧:

rhs =harmonicsum + log(harmonicsum) .* exp(harmonicsum);

我无法向量化这些因素的确定,所以这是我能想到的对它们求和的最快方法。 MATLAB 的FACTOR 命令允许您为每次迭代生成所有主要因子。然后,我们使用UNIQUENCHOOSEK 计算所有可能组合的唯一乘积集。这避免了将每个整数作为一个因素进行测试。

lhs = 零(1e6,1); 对于 ii = 1:1e6 primeFactor = 因子(ii); numFactor = 长度(primeFactor); allFactor = []; 对于 jj = 1:numFactor-1 allFactor = [allFactor;独特的(产品(nchoosek(primeFactor,jj),2))]; 结尾 lhs(ii) = sum(allFactor) + 1 + ii; 结尾 lhs(1) = 1;

找出违反黎曼假设的指数:

isViolated = find(lhs > rhs);

【讨论】:

  • 据我所知,lhs(1)lhs(2)lhs(3) 以及其他所有可能的结果都是错误的。
  • 运行原始代码从问题中找到lhs(1:10),我的现在匹配,你的不匹配,不是单个元素:(
  • 我认为问题(除了ii == 1 的情况)是jj == numFactor 产生ii 本身,你单独计算。把循环改成jj = 1:numFactor应该会更好。
  • 应该是说“把循环改成for jj = 1:numFactor-1”。
  • 我的老师能够在不到一分钟的时间内运行这段代码。有没有其他你能想到的方式来表达这段代码?
【解决方案3】:

@b3 has a great vectorization of rhs.

不过有一个错字,需要使用times 而不是mtimes

harmonicsum = cumsum(1 ./ (1:1e6));
rhs = harmonicsum + log(harmonicsum) .* exp(harmonicsum);

对于lhs,我大致基于 Eratosthenes 的筛子提出以下建议:

lhs = 1 + [1:1e6];
lhs(1) = 1;
for iii = 2:numel(lhs)/2
    lhs(2*iii:iii:end) = lhs(2*iii:iii:end) + iii;
end;

执行时间仅为 2.45 秒(对于这半个问题)。包括 rhsfind 的计算在内的总计不到 3 秒。

我目前正在运行其他版本以确保结果相同。


编辑:发现lhs(1) 的错误并对其进行特殊处理(这是一种特殊情况,唯一的自然数,其中 1 和 N 不是不同的因数)

【讨论】:

  • 感谢您发现错字。 lhs 的计算做得很好。我认为您所需要的只是将 1 添加到整个向量。
  • 对于谐波和,我需要把它放在循环中吗?我不了解您的代码如何对 i 的每个值进行谐波求和?
  • @icobes:这就是cumsum 的魔力。注意harmonicsum(i) = harmonicsum(i-1) + 1/i.
  • +1 这非常快.. 它在 3 秒内计算 n 的 sum of divisors,对于 1 到 1000000 之间的所有 n!我尝试了该页面上列出的一些代码,Mathematica 版本花了 15 秒,MuPad 版本大约 100 秒......
猜你喜欢
  • 1970-01-01
  • 2011-11-03
  • 2013-11-12
  • 2016-10-21
  • 2018-03-14
  • 2013-05-01
  • 2012-10-05
  • 2019-05-31
  • 2011-11-03
相关资源
最近更新 更多