2012-12-19 18 views
3

我有一個調用函數的代碼,它給出了系統中每個基因的類型。我可以通過比較每個基因與其孩子和父母的順序來找到它。代碼工作正常,只有一小部分單元陣列,但是當我將數量增加到數千時,需要花費數小時。的代碼是:在Matlab中增加函數調用的速度

Types=[]; 
type1=level1_root; % it is fixed value (GO:0008150) 
% sample values for p1 and c1 are given below 
for k=1:100 
    type{k}=type_fc(p1,c1,type1); % a function call - see function below 
    type1=type{k}'; %' 
    temp1=num2cell(repmat(k+1,length(type1),1)); 
    type1=[type1 temp1]; 
    Types=[Types; type1]; 
end 
% display the output: 
Types 

子功能:

function type=type_fc(p1,c1,type1) 
type=[]; 
for j=1:length(type1) 
    for i=1:length(p1) 
     a=[p1(i),c1(i)]; 
     if isequal(a(1), type1(j)) 
      type=[type a(2)]; 
     end 
    end 
end 

對於13個基因我有這些採樣輸入:

p1'= %refer to parent genes 
     'GO:0008150' 
     'GO:0016740' 
     'GO:0016787' 
     'GO:0008150' 
     'GO:0016740' 
     'GO:0016740' 
     'GO:0016787' 
     'GO:0016787' 
     'GO:0016787' 
     'GO:0006810' 
     'GO:0006412' 
     'GO:0004672' 


c1'= % refer to children genes  
    'GO:0016740' 
    'GO:0016787' 
    'GO:0006810' 
    'GO:0006412' 
    'GO:0004672' 
    'GO:0016779' 
    'GO:0004386' 
    'GO:0003774' 
    'GO:0016298' 
    'GO:0016192' 
    'GO:0005215' 
    'GO:0030533' 

而結果將是:Types =

'GO:0016740' [2] 
    'GO:0006412' [2] 
    'GO:0016787' [3] 
    'GO:0004672' [3] 
    'GO:0016779' [3] 
    'GO:0005215' [3] 
    'GO:0006810' [4] 
    'GO:0004386' [4] 
    'GO:0003774' [4] 
    'GO:0016298' [4] 
    'GO:0030533' [4] 
    'GO:0016192' [5] 

你有沒有任何想法如何提高這段代碼的速度?

+0

如果你有類似的問題,你可以試試[codereview](http://codereview.stackexchange.com) –

回答

7

乍一看,我可以在你的代碼發現一些問題:

  1. 首先,Typestype動態循環內增長。在執行時間方面,這在MATLAB中可能非常昂貴。相反,在循環之前預先分配內存(即,使用預定的最終數量的元素創建數組),並且您可能會看到性能的急劇增加。

  2. 您正在使用循環。如果有矢量化解決方案(我還沒有檢查過),則可能需要更少的時間進行計算。

  3. 您正在使用ij索引作爲循環迭代器的變量名稱。這些變量已經有另一個目的:它們代表虛構單位sqrt(-1)。 MATLAB仍允許使用ij作爲變量名稱,但是爲了找出正確的上下文而做的變量名稱解析確實有很小的成本。您應該選擇其他名稱,即使是iijj
    編輯:同樣爲type,它已經是MATLAB中的reserved function name

試試下面的優化版本,它應該運行至少一個數量級的速度更快:

Types = cell(numel(c1), 2);  % # Preallocate memory 
type1 = level1_root;    % # ... or p1{1} 
kk = [1, 2];      % # Initialize indices 
while ~isempty(type1) 
    type_fc = cellfun(@(x)c1(strcmp(x, p1)), type1, 'Uniform', false); 
    type1 = vertcat(type_fc{:}); 
    idx = kk(1):kk(1) + numel(type1) - 1; 
    Types(idx, 1) = type1; 
    Types(idx, 2) = {kk(2)}; 
    kk = kk + [numel(type1), 1]; % # Advance indices 
end 
Types = Types(1:kk(1) - 1, :); % # Remove empty output cells 
+0

實際上我知道預分配是個大問題,對於所有變量,但有些給出錯誤..因爲Iam處理單元格數組。例如:我有這個代碼,它不能給出初始值:b = {};對於i = 1: 長度(地圖) b = [b,map {i,1}]; end – Gloria

+1

@Gloria其實你可以預測它。你可以在map中的每個單元格中計算相關的元素數量,總和將是'b'所需的大小。我將發佈代碼的優化版本,並希望您會發現其執行時間足夠快。 –

+0

我試過b =零(長度(地圖)),它不起作用(給出錯誤消息),雖然地圖的長度是13,b也是13! thnak你的支持:)) – Gloria

2

如果我正確地讀它,然後該功能在1型比較值與p1中的父親基因一起發現匹配,然後從c1返回相應的孩子基因。它是否正確?

在這種情況下,矢量化解決方案使用strcmp來獲取type1(j)和p1之間匹配的邏輯數組。

>> strcmp(type1(j),p1) 

然後這可以用於數組c1上的邏輯尋址,這實際上是您想要提取的c1值的真值表。我假設你正在處理這些細胞陣列,在這種情況下,我認爲應該這樣做。

function type=type_fc(p1,c1,type1) 
type={}; 
for j=1:length(type1) 
    type=[type{:} c1(strcmp(type1(j),p1))']; 
end 

現在是否它使得它更快,我不知道,我希望你能測試它。這是我對「矢量化」解決方案的建議。

+1

我相信你對'type_fc'的建議會返回一個完全不同於OP的答案。 –

+1

其實我認爲它是非常親密的,我的錯誤是我覆蓋'j'上的每個循環的變量'type'。代碼已更正。如果你創建p1和c1作爲單元格數組,並且'type1 = {'GO:0008150'}'那麼對於第一次迭代,這兩個函數都會返回''GO:0016740''GO:0006412',然後將它反饋回函數,將返回''GO:0016787''GO:0004672''GO:0016779''GO:0005215''這是'Types'中的前6個值。 – Adrian

+1

正確。但主要問題仍然是動態增長的數組:-) –