优化MATLAB代码

时间:2011-10-03 19:58:43

标签: performance matlab vectorization

此代码需要很长时间才能运行(超过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

3 个答案:

答案 0 :(得分:6)

@b3 has a great vectorization of rhs.

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

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

对于lhs,我基于Eratosthenes的Sieve松散地提出以下建议:

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不是不同的因素)

答案 1 :(得分:4)

将算法矢量化,我可以将执行时间略微缩短到约8.5分钟。在一个陈述中计算所有的谐波总和:

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

您现在可以在一个声明中计算右侧:

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

我无法对因子的确定进行矢量化,因此这是我能想出的最快的方法。 MATLAB的FACTOR命令允许您为每次迭代生成所有素因子。然后,我们使用UNIQUENCHOOSEK计算所有可能组合的唯一产品集。这避免了将每个整数作为一个因子进行测试。

lhs = zeros(1e6, 1);
for ii = 1:1e6
    primeFactor = factor(ii);
    numFactor = length(primeFactor);
    allFactor = [];
    for jj = 1:numFactor-1
       allFactor = [allFactor; unique(prod(nchoosek(primeFactor, jj), 2))];
    end
    lhs(ii) = sum(allFactor) + 1 + ii;
end
lhs(1) = 1;

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

isViolated = find(lhs > rhs);

答案 2 :(得分:0)

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