簡體   English   中英

加快查找值之間的元素數量 Matlab

[英]Speed Up Finding Number of Elements Between Values Matlab

我創建了一個相當簡單的 MATLAB 腳本來模擬Maths SE 上這個問題中討論的行為。

clearvars;
samples = 1000;
x = 256;
r=exprnd(1/20e6,1,samples); % Generate exponentially distributed randoms.
endTime = sum(r);
quickMean=sum(r(1:x))/x; % Quick calc the mean and median.
quickMedian=0.693 * quickMean;
p = cumsum(r); % Convert event deltas into timestamps
bitstream = false(1,samples);
time = 0;
lastTime = 0;
for i = 1:samples
    lastTime = time;
    time = time + quickMedian;
    if (numel(p(p < time & p > lastTime)) > 0)
        bitstream(i) = true;
    end
    if (time > p(end))
        break
    end
end
ratio = sum(bitstream)/samples;

該腳本似乎有效,但是,如果我使用大量樣本(比如一百萬),這將是有益的,它真的會爬行。

我假設有問題的陳述是這個:

p(p < time & p > lastTime)

是否有更有效的方法來檢查數組中的任何元素是否介於兩個值之間?

讓我們檢查一下整個表達式:

numel(p(p < time & p > lastTime)) > 0

為了清楚起見,我們可以將其分開:

I = p < time & p > lastTime;
tmp = p(I);
n = numel(tmp);
n > 0

在這里, tmp的創建非常昂貴:它查看I的真實位置,並將這些元素復制到一個新數組中。 但是您對這個數組所做的唯一事情就是查看它有多少元素。 邏輯上n將等於I中真實元素的數量。 而你並不真正需要這個數字,你只需要知道它是否大於 0。也就是說,你想知道I為真。 您可以使用any

any(p < time & p > lastTime)

正如我在評論中提到的,我們可以利用p單調遞增的事實並忽略小於lastTime的值。 如果我們找到p < time的最后一個值,那么在下一次迭代( lastTime )中,只有右邊的值可以大於* time

clearvars;
samples = 1000;
x = 256;
r=exprnd(1/20e6,1,samples); % Generate exponentially distributed randoms.
endTime = sum(r);
quickMean=sum(r(1:x))/x; % Quick calc the mean and median.
quickMedian=0.693 * quickMean;
p = cumsum(r); % Convert event deltas into timestamps
bitstream = false(1,samples);
time = 0;
lastTime = 0;

% code is the same up to here ---

lastTimeIdx = 1; % index of (last value < lastTime) + 1
for i = 1:samples
    lastTime = time;
    time = time + quickMedian;

    valsInRange = p(lastTimeIdx:end) < time; % p > lastTime & p < time
    timeIdx = find(valsInRange, 1, 'last'); % returns [] or index

    if ~isempty(timeIdx)
        bitstream(i) = true;
        lastTimeIdx = lastTimeIdx + timeIdx; % update start of next search
    end
    if (time > p(end))
        break
    end
end
ratio = sum(bitstream)/samples;

*其實這是“大於等於”,但是由於p的值是唯一的,所以它們是一回事。


好的,我剛剛在 Octave 中嘗試histc 我很尷尬地說它快得離譜。 快了 4 個數量級。 這是我使用的代碼,但histc在 MATLAB 中已棄用,並且histcounts的分箱不同,因此您可能需要稍微嘗試一下。

bitstream_hist = histc(p, [0:samples]*quickMedian) > 0;
bitstream_hist = bitstream_hist(1:samples);

一百萬個樣本在幾分之一秒內完成。 抱歉我沒有早點想到這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM