3

データのブロックを含む 2D 配列があり、各値がゼロを横切る回数を計算する関数を作成しました。

私は MatLab を使用してコードを変換しようとしていますが、MatLab はゼロクロッシングに対して 287 の値を返し、C++ コードでは値が非常に高く、その理由がわかりません。

Matlab コードは次のとおりです。

function f = zerocross(vector)

% This function simply reports the number of times
% that the input vector crosses the zero boundary

len = length(vector);
currsum = 0;
prevsign = 0;

for i = 1:len
currsign = sign(vector(i));
if (currsign * prevsign) == -1 
  currsum = currsum + 1;
end
if currsign ~= 0
  prevsign = currsign;
end
end

f = currsum;

そして私のC++コード:

vector<iniMatrix> Audio::filter(vector<iniMatrix>&blocks, double sumThres, double ZeroThres)
{
 double totalSum = this->width * sumThres;
 double totalZero = this->width * ZeroThres;

int currZero = 0;
int currsum = 0;

int prevsign = 0;


for(unsigned i=0; (i < 287); i++)
{
    for(int j=0; (j < blocks.size()); j++)
    {
        currZero = sign<double>(blocks[j][i]);

        if(currZero * prevsign == -1)
        {
            currsum++;
        }

        if(currZero != 0)
        {
            prevsign = currZero;
        }
    }
    cout << currsum << endl;
}

return blocks;

サイン機能:

int sign(T n)
{
  if(n < 0) return -1;
  if(n > 0) return 1;
  return n;
}

私がすべき(そしてmatlabが与える)値は次のとおりです。

6, 6, 7, 9, 9, 10 .., 11, ..., 9, ...

私が得る値:

212, 337, 118, 84, ...., 348, ..., 92

誰にもアイデアはありますか?

編集:

これは私が今私のループを持っている方法です:

for(int q=0; (q < 287); q++)
{
    for(unsigned i=0; (i < blocks.size()); i++)
    {
        for(unsigned j=0; (j < blocks[0].size()); j++)
        {
            currZero = sign<double>(blocks[i][j]);
            cout << currZero << endl;
        }
        cout << endl << endl << endl;

    }
    //cout << currZero << endl;
}
4

1 に答える 1

0

Matlab で for ループを多用することは、Matlab の JIT コンパイラが非常に高速ではない (またはそうでなかった) ため (少なくともネイティブ C コードと比較して)、伝統的に通常は悪い考えでした。計算を高速化するために C++ コードを作成したと思いますが、代わりに「matlab の方法」でコードを作成することもできます。

vector = rand(1e7,1)-0.1;
zero_crossings = sum(diff(array<0)~=0);

Matlab 2015b でテストしたばかりですが、ベクトル化されたコードでは約 2 倍の速度しかありません。

function test()

    function currsum = zerocross(vector)

        % This function simply reports the number of times
        % that the input vector crosses the zero boundary

        len = length(vector);
        currsum = 0;
        prevsign = 0;

        for i = 1:len
            currsign = sign(vector(i));
            if (currsign * prevsign) == -1
                currsum = currsum + 1;
            end
            if currsign ~= 0
                prevsign = currsign;
            end
        end
    end

    function f = zerocross_vectorized(array)
        f = sum(diff(array<0)~=0);
    end

    array = rand(1e5,1e3)-0.1;

    % test for loop
    t = tic;
    crossings = nan(1,size(array,2));
    for column = 1:size(array,2)
        vector = array(:,column);
        crossings(column) = zerocross(vector);
    end
    disp(crossings(1:5))
    fprintf(1,'For loop: Calculated in %0.4f seconds\n',toc(t));

    % test vectorized
    t = tic;
    crossings = zerocross_vectorized(array);
    disp(crossings(1:5))
    fprintf(1,'Vectorized: Calculated in %0.4f seconds\n',toc(t));

end

結果は次のとおりです。

>> zerocross
       18208       17884       17902       17734       17988

For loop: Calculated in 1.7186 seconds
       18208       17884       17902       17734       17988

Vectorized: Calculated in 0.9695 seconds
于 2015-11-10T18:54:18.023 に答える