2012-02-01 21 views
0

私はMatlabのプロファイラで次のコードを実行しました。これは不要なループであると感じるので、このコードをベクトル化することは非常に重要です。matlabでxor演算をベクトル化する方法

私は2つの行列Gとsource_dataを持っています。 Gのすべての列は、私がsource_dataからピックアップしてそれらを一緒にxorする必要がある行を決定します。

Iは、以下のforループ

for i=1:10 
source_data(i,:)=rand(1,20)<.8; 
end 

for i=1:15 
G(:,i)=rand(10,1)<.9; 
end 

私は使用してXOR演算を行っており、次のコード片を用いてGとsource_dataを作成しています:

z=1; 
while(i<=15) 
for j=1:10 
    if(G(j,i)==1) 
     intersum(z+1,:)=xor(intersum(z,:), source_data(j,:)); 
     z=z+1; 
    end 
end 
C(i,:)=intersum(z,:); 
i=i+1; 
end 

このコードをvectoriseする方法はあります?タイムラグは小さな行列では受け入れられますが、大きな行列ではこのコードはかなり効率的です。

おかげで、

バウィヤ

+0

最後のループで 'i'とは何があり、' K'とは何ですか? 'xor'自体は既にベクトル化されています。おそらくそれはあなたのために役立ちます:http://www.mathworks.de/help/techdoc/ref/xor.htmlそうでなければ' arrayfun'を見てください – tim

+0

@Alexandrewこれを指摘してくれてありがとう上記の質問を編集して – bhavs

答えて

1

と仮定すると:

  • 私は1
  • intersumから始まるが

はここで生産するあなたのコードのベクトル化フォームのゼロから始まりますあなたのオリジナルと同じ結果:

function C = version_a() 
    source_data = rand(10,20)<.8; 
    G = rand(10,15)<.9; 

    intersum = zeros(1, size(source_data,2)); 
    z = 1; 
    i = 1; 
    while i <= 15 
    for j=1:10 
     if(G(j,i)==1) 
      intersum(z+1,:)=xor(intersum(z,:), source_data(j,:)); 
      z=z+1; 
     end 
    end 

    C(i,:)=intersum(z,:); 
    i=i+1; 
    end 
    ret = C; 
end 

function C = version_b() 
    source_data = rand(10,20)<.8; % Can initialize in a single call 
    G = rand(10,15)<.9;   % Same here 
    C = zeros(size(G,2),size(source_data,2)); 

    C(1,:) = mod(sum(source_data(G(:,1),:)),2); 
    for i = 2:15 
    C(i,:) = mod(C(i-1,:) + sum(source_data(G(:,i),:)),2); 
    end 
end 

両方のバージョンのタイミングを確認するには、私は、このテスト機能を使用:

function ret = xor_test() 
    ret = 0; 

    seed = 123456789; 
    laps = 10000; 

    tic 
    for i = 1:laps 
    RandStream.getDefaultStream.reset(seed); 
    a = version_a(); 
    end 
    toc 

    tic 
    for i = 1:laps 
    RandStream.getDefaultStream.reset(seed); 
    b = version_b(); 
    end 
    toc 

    ret = ret + sum(sum(b ~= a)); 
end 

をそして私は私のマシン上で次のタイミングだ:私はそれを変更する理由に今

Elapsed time is 13.537738 seconds. 
Elapsed time is 2.302747 seconds. 
ans = 
    0 

をそうですね...

xorlogicalの配列上での操作はかなりchecですキングの総額(trueの値を1として扱う)。 Furhtermore intersumはアキュムレータとして使用されていますので、値は最終的にCになります。そのため、すべてを省略します。 G(j,i)が1である行を取ることはlogical indexingによって行うことができます。

最後に、この提案されたバージョンが気に入らなくても、あなたのCintersumベクターを事前に割り当てることをお勧めします。それは過去に私にとって大きな違いをもたらしました。

+0

このコードをありがとうございます。それは確かに以前のバージョンよりも多くのフェスターを実行します。しかし、私は行の賢明さをチェックしていましたが、両方の関数で生成された行列Cがisequalメソッドを使用していて、それらがかなり異なっていることがわかりました。 – bhavs

+0

ちょうど...あなたは同じ 'G'と' source_data'を使用していますか?たとえあなたがRNGを再提出しても、以前と同じように数字を生成しても、結果は異なります。だから、 'version_a'でも' G'と 'source_data'を生成するように変更しました。 – Pablo

+0

上記のコードを使用しており、ベクトル化されたxor演算の結果と上記の広範なforループのxor演算とを比較しようとしています。両方のケースでエンコードされたデータマトリックスを比較すると、私は別の結果を得ています。 – bhavs

関連する問題