2016-08-18 32 views
1

通常情況下,如果在每次迭代中需要生成一個隨機數,最好在開始時生成所有隨機數,然後在每次迭代中生成一次,您可以檢索您從表中生成的數字。生成循環外的所有隨機數還是動態生成它會更好嗎

但是,我今天遇到了一個與這個直覺相反的問題。我有一個長度爲N的數字向量,在每次迭代中,我必須重新組合這個向量的順序並做一些事情。

我實現2種方式:第一種是完全按照我剛纔所描述的,即,在每次迭代中,我調用函數

V = randperm(N) 

在第二方法中,在循環之前,我調用函數

W = arrayfun(@(x)randperm(N),(1:T-1)','UniformOutput',0); 
W = cell2mat(W); 

這裏T是迭代的總數。然後在每次迭代中,我只是從矩陣W中檢索行。然後2個方法的其餘代碼完全相同。

但是,我發現第二個代碼比第一個代碼慢得多(我檢查了命令:W = arrayfun(@(x)randperm(N),(1:T-1)','UniformOutput',0);不需要太多時間)。我運行分析器,我發現在第二個代碼中調用函數ismember>ismemberR2012a比第一個代碼多3倍。我無法弄清楚爲什麼。

+0

是否需要使用'r andperm',而不是像'randi'這可以給你一個大的隨機矩陣? – Matt

回答

0

首先您應該注意,randpermarrayfun這兩個函數都是作爲mex文件實現的。所以我的第一個猜測是arrayfun是一個調用randperm並將其結果存儲在cell並重復此過程的過程。這使它慢一點。如果您嘗試在第一個解決方案中執行相同的操作,則成本會更高。 我也進行了一些測試。 我不知道NT的規模。不過還是我測試的功能我的機器

N=10000; 
T = 1000; 
tic; 
for ii=1:T-1 
    V=randperm(N); 
end 
toc; 
tic; 
W = arrayfun(@(x)randperm(N),(1:T-1)','UniformOutput',0); 
W = cell2mat(W); 
toc; 

上,其結果是:

對於N=10000T=1000

Elapsed time is 0.849627 seconds. 
Elapsed time is 0.996933 seconds. 

我想原因是,第一個解決方案被稱爲T-1倍,而第二個只被調用一次。它必須管理大單元分配。

enter image description here

即使這樣做並不會提高代碼的性能,許多:

tic; 
for ii=1:T-1 
Z = arrayfun(@(x)randperm(N),ii,'UniformOutput',0); 
end 
toc; 

Elapsed time is 0.827387 seconds. 
Elapsed time is 0.966013 seconds. 
Elapsed time is 0.951093 seconds. 

然後運行分析器: enter image description here

  • 如果你能生成隨機數在飛行中,生成和存儲它們的要點是什麼,然後在需要時重新加載它們?

  • 這些數字是在不同的運行中收集的,顯然是由於執行時間的隨機性,它們不一致。

+0

所以看來最好是在每次迭代中分別運行randperm(N)。記憶在這種情況下也會成爲問題嗎?如果我們在每次迭代中調用randperm(N),那麼它的名字會比我們沒有循環的一次調用消耗很少的內存。 – ftxx

+0

當需要的時候我會調用它一次。 – NKN

0

只是做附註:如果N小於10時,您可能需要使用perms

循環之前:

% get all available permutations: 
W = perms(1:N); 
% get a list of T random permutations from W: 
p = randi(length(W),T,1); 

然後用pW內環路:

V = W(p(k),:); % for iteration k