ベクトル化を解除することで実際にこれを解決できると思います。つまり、事前定義された配列と単純な操作のみを使用して、高レベルの呼び出しと高価な操作をすべて削除し、本質的なものにまで落とします。
アルゴリズムのコアは次のようになります。
重みの合計を決定する
0 から重みの合計までの n 個の乱数を選択し、並べ替えます。
cumsum ループを手動で実装します。ただし、すべての累積合計を保存するのではなく、累積合計が現在の乱数未満から現在の乱数を超えるインデックスのみを保存します。
コードでは (少しタイミング リグを使用)、次のようになります。
tic
for ixTiming = 1:1000
M = abs(randn(50));
M_size = size(M, 2);
n = 8;
total = sum(M(:));
randIndexes = sort(rand(n,1) * total);
list = zeros(n,1);
ixM = 1;
ixNextList = 1;
curSum = 0;
while ixNextList<=n && ixM<numel(M)
while curSum<randIndexes(ixNextList) && ixM<=numel(M)
curSum = curSum+M(ixM);
ixM = ixM + 1;
end
list(ixNextList) = ixM;
ixNextList = ixNextList+1;
end
[i_list, j_list] = ind2sub(size(M),list);
end
toc; %0.216 sec. on my computer
これを元の質問のコードと比較してください。
tic
for ixTiming = 1:1000
M = abs(randn(50));
M_size = size(M, 2);
n = 8;
for m = 1:M_size
xMean(m) = mean(M(:, m));
end
[~, j_list] = histc(rand(n, 1), cumsum([0; xMean'./sum(xMean)']));
for c = 1:n
[~, i_list(c)] = ...
histc(rand(1, 1), cumsum([0;, M(:, j_list(c))./sum(M(:, j_list(c)))]));
end
end
toc; %1.10 sec on my computer
警告と最適化。