有意减慢MATLAB功能?

时间:2009-10-23 21:56:27

标签: debugging matlab performance distributed-computing

我想为MATLAB写一个非常非常慢的程序。我说的是,O(2 ^ n)或更糟。它必须完成,并且必须确定性地缓慢,所以没有“如果rand()= 123,123,退出!”这听起来很疯狂,但它实际上是用于分布式系统测试。我需要创建一个.m文件,编译它(使用MCC),然后在我的分布式系统上运行它来执行一些调试操作。

程序必须不断地工作,因此sleep()不是一个有效的选项。

我尝试制作一个随机的大矩阵并找到它的逆矩阵,但这很快就完成了。有什么想法吗?

11 个答案:

答案 0 :(得分:4)

数到2 n 。 (可选)在每次迭代中进行慢速函数调用。

答案 1 :(得分:4)

如果你想要真正的工作,这很容易设置,并强调CPU方式超过内存:

  • 大密度矩阵反转(不够慢?让它变大。)
  • 因素RSA number

答案 2 :(得分:4)

对于我的1.86 GHz单核机器上的2048长输入向量x,离散傅里叶变换的这种天真实现需要大约9秒。进入4096输入将时间延长到~35秒,接近我期望的O(N ^ 2)的4倍。我没有耐心尝试更长时间的投入:)

function y = SlowDFT(x)

t = cputime;
y = zeros(size(x));
for c1=1:length(x)
    for c2=1:length(x)
        y(c1) = y(c1) + x(c2)*(cos((c1-1)*(c2-1)*2*pi/length(x)) - ...
                            1j*sin((c1-1)*(c2-1)*2*pi/length(x)));
    end
end
disp(cputime-t);

编辑:或者,如果你想要比CPU强调内存:

function y = SlowDFT_MemLookup(x)

t = cputime;
y = zeros(size(x));
cosbuf = cos((0:1:(length(x)-1))*2*pi/length(x));
for c1=1:length(x)
    cosctr = 1;
    sinctr = round(3*length(x)/4)+1;
    for c2=1:length(x)
         y(c1) = y(c1) + x(c2)*(cosbuf(cosctr) ...
                            -1j*cosbuf(sinctr));
         cosctr = cosctr + (c1-1);
         if cosctr > length(x), cosctr = cosctr - length(x); end
         sinctr = sinctr + (c1-1);
         if sinctr > length(x), sinctr = sinctr - length(x); end
    end
end
disp(cputime-t);

这比在每次迭代时计算sin和cos更快。一个2048长的输入需要大约3秒钟,一个16384长的输入需要大约180秒。

答案 3 :(得分:3)

如何使用inv? reported速度很慢。

答案 4 :(得分:2)

我不会说MATLAB,但以下内容可能会有效。

loops = 0
counter = 0
while (loops < MAX_INT) {
    counter = counter + 1;
    if (counter == MAX_INT) {
        loops = loops + 1;
        counter = 0;
    }
}

这将迭代MAX_INT * MAX_INT次。你可以在循环中加入一些计算量很大的东西,如果这还不够,可以花更长的时间。

答案 5 :(得分:2)

在循环中做一些工作。您可以使用循环迭代次数来调整完成所需的时间。

答案 6 :(得分:2)

轻松!回到你的图灵机根,想一想O(2 ^ n)或更差的过程。

这是一个相当简单的问题(警告,未经测试,但你明白了)

N = 12; radix = 10;
odometer = zeros(N, 1);
done = false;
while (~done)
    done = true;
    for i = 1:N
        odometer(i) = odometer(i) + 1;
        if (odometer(i) >= radix)
            odometer(i) = 0;
        else
            done = false;
            break;
        end
    end
end

更好的是,如何递归计算斐波纳契数?运行时间为O(2 ^ N),因为fib(N)必须进行两个函数调用fib(N-1)和fib(N-2),但堆栈深度为O(N),因为只有其中一个函数调用一次发生。

function y = fib(n)
   if (n <= 1)
      y = 1;
   else
      y = fib(n-1) + fib(n-2);
   end
end

答案 7 :(得分:1)

您可以向factor(X)询问适当大的X

答案 8 :(得分:1)

您还可以通过将其除以所有较小的数字来测试给定输入是否为素数。这会给你O(n ^ 2)。

答案 9 :(得分:1)

试试这个:

tic
isprime( primes(99999999) );
toc

修改

对于更广泛的测试集,请使用这些基准测试(甚至可能多次重复):

disp(repmat('-',1,85))
disp(['MATLAB Version ' version])
disp(['Operating System: ' system_dependent('getos')])
disp(['Java VM Version: ' version('-java')]);
disp(['Date: ' date])
disp(repmat('-',1,85))

N = 3000;   % matrix size
A = rand(N,N);  
A = A*A;

tic;  A*A; t=toc;
fprintf('A*A \t\t\t%f sec\n', t)

tic; [L,U,P] = lu(A); t=toc; clear L U P
fprintf('LU(A)\t\t\t%f sec\n', t)

tic; inv(A); t=toc;
fprintf('INV(A)\t\t\t%f sec\n', t)

tic; [U,S,V] = svd(A); t=toc; clear U S V
fprintf('SVD(A)\t\t\t%f sec\n', t)

tic; [Q,R,P] = qr(A); t=toc; clear Q R P
fprintf('QR(A)\t\t\t%f sec\n', t)

tic; [V,D] = eig(A); t=toc; clear V D
fprintf('EIG(A)\t\t\t%f sec\n', t)

tic; det(A); t=toc;
fprintf('DET(A)\t\t\t%f sec\n', t)

tic; rank(A); t=toc;
fprintf('RANK(A)\t\t\t%f sec\n', t)

tic; cond(A); t=toc;
fprintf('COND(A)\t\t\t%f sec\n', t)

tic; sqrtm(A); t=toc;
fprintf('SQRTM(A)\t\t%f sec\n', t)

tic; fft(A(:)); t=toc;
fprintf('FFT\t\t\t%f sec\n', t)

tic; isprime(primes(10^7)); t=toc;
fprintf('Primes\t\t\t%f sec\n', t)

以下是我的机器上仅使用N = 1000进行一次迭代的结果(注意质数用作上限10 ^ 7 NOT 10 ^ 8 [花费更多时间!]

A*A             0.178329 sec
LU(A)           0.118864 sec
INV(A)          0.319275 sec
SVD(A)          15.236875 sec
QR(A)           0.841982 sec
EIG(A)          3.967812 sec
DET(A)          0.121882 sec
RANK(A)         1.813042 sec
COND(A)         1.809365 sec
SQRTM(A)        22.750331 sec
FFT             0.113233 sec
Primes          27.080918 sec

答案 10 :(得分:1)

这将为WANTED_TIME秒运行100%cpu

WANTED_TIME = 2^n; % seconds
t0=cputime; 
t=cputime; 
while (t-t0 < WANTED_TIME)
    t=cputime; 
end;