利用matlab/octave实现环路和中频稳定及提速

利用matlab/octave实现环路和中频稳定及提速,matlab,octave,Matlab,Octave,我想看看是否可以提高for循环和if条件语句的速度。基本上,它在数组中查找非重复键值,并从另一列获取值 如果运行100000个值,大约需要13秒请参见下面的代码。有没有办法让这更有效?Ps我正在使用octave 3.8.1,它与matlab一起工作 %test if lookup statment clear all, clc, tic, clf; num_to_test=100000 %amount of numbers to test a1=(1:1:num_to_test)'; a2

我想看看是否可以提高for循环和if条件语句的速度。基本上,它在数组中查找非重复键值,并从另一列获取值

如果运行100000个值,大约需要13秒请参见下面的代码。有没有办法让这更有效?Ps我正在使用octave 3.8.1,它与matlab一起工作

%test if lookup statment
clear all, clc,  tic, clf; 

num_to_test=100000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random values of non repeating integers and floats and get another value

amp=[];
freq=[];
found_array=[];
notfound_array=[];

for ii=1:1:rows(lookupval)
    if (find(lookupval(ii)==array(:,1)))  %if you find a lookup value in array
        %disp('found');
        [row,col] = find(lookupval(ii) == array(:,1));
        amp=[amp;array(row,2)];
        freq=[freq;array(row,1)];
        found_array=[freq,amp];

    else %add lookup value to another array and make amp value zero

        notfound_arraytmp=[lookupval(ii),0];
        notfound_array=[notfound_array;notfound_arraytmp];
    endif
end
comb_array=[found_array;notfound_array];
sort_comb_array=sortrows(comb_array,1); %sort array by first col incrementing

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

有几个问题,但主要的问题可能是您没有像这样预先分配-追加:
amp=[amp;array(row,2)]在MATLAB中通常速度较慢。不过,这里不需要循环

让我们从一个简单的数组开始:

1  500
2  700
3  900
7  1000
9  800
我们的查找值是
[2 6 3 9 7]我们希望输出在第一列中显示这些已排序的查找值,第二列是A的第二列中的值(如果存在)或零

输出为:

2 700
3 900
6 0
7 1000
9 800

有几个问题,但主要的问题可能是您没有像这样预先分配-追加:
amp=[amp;array(row,2)]在MATLAB中通常速度较慢。不过,这里不需要循环

让我们从一个简单的数组开始:

1  500
2  700
3  900
7  1000
9  800
我们的查找值是
[2 6 3 9 7]我们希望输出在第一列中显示这些已排序的查找值,第二列是A的第二列中的值(如果存在)或零

输出为:

2 700
3 900
6 0
7 1000
9 800

纯粹从效率的角度来看,我会将
for
循环重写如下:

m = 0;                          % number of omitted values
n = 0;                          % number of found values
for ii=1:1:rows(lookupval)

    [row,col] = find(lookupval(ii) == array(:,1));

    if ~isempty(row)  %if you find a lookup value in array
        %disp('found');
        n=n+1;
        amp(n)=array(row,2);
        freq(n)=;array(row,1);
        found_array=[freq,amp];

    else %add lookup value to another array and make amp value zero
        m=m+1;
        notfound_array(2*m-1:2*m)=[lookupval(ii);0];
    endif
end

通过直接使用其输出,而不是在
find
返回位置时重新计算它,从而节省了
find
调用,并以更有效的方式增长数组(如中所示)。

纯粹从效率的角度来看,我将重写
for
循环,如下所示:

m = 0;                          % number of omitted values
n = 0;                          % number of found values
for ii=1:1:rows(lookupval)

    [row,col] = find(lookupval(ii) == array(:,1));

    if ~isempty(row)  %if you find a lookup value in array
        %disp('found');
        n=n+1;
        amp(n)=array(row,2);
        freq(n)=;array(row,1);
        found_array=[freq,amp];

    else %add lookup value to another array and make amp value zero
        m=m+1;
        notfound_array(2*m-1:2*m)=[lookupval(ii);0];
    endif
end
这可以通过直接使用其输出而不是在
find
返回位置时重新计算它来节省
find
调用,并以更有效的方式增长数组(如所示)。

方法#1

使用-

lookupval = sort(lookupval);                     %// Do sorting at the start
sort_comb_array = [lookupval zeros(size(lookupval))]; %// Setup output array
[idA,idB] = ismember(array(:,1),lookupval);           %// Get matching IDs
sort_comb_array(idB(idA),2) = array(idA,2);  %// Index into second column
                                   %// of array and get corresponding values
方法#2

我也会加入我最喜欢的,但是对于如此巨大的
100000
数据量,它的内存效率低下可能会使它变得更慢-

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA,idB] = find(bsxfun(@eq,array(:,1),lookupval(:).')); %//'# Get matching IDs
sort_comb_array(idB,2) = array(idA,2);
方法#1

使用-

lookupval = sort(lookupval);                     %// Do sorting at the start
sort_comb_array = [lookupval zeros(size(lookupval))]; %// Setup output array
[idA,idB] = ismember(array(:,1),lookupval);           %// Get matching IDs
sort_comb_array(idB(idA),2) = array(idA,2);  %// Index into second column
                                   %// of array and get corresponding values
方法#2

我也会加入我最喜欢的,但是对于如此巨大的
100000
数据量,它的内存效率低下可能会使它变得更慢-

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA,idB] = find(bsxfun(@eq,array(:,1),lookupval(:).')); %//'# Get matching IDs
sort_comb_array(idB,2) = array(idA,2);

这是一个测试Divakar建议我做,看看它的速度需要倍频程3.8.1运行这个。下面是结果和代码

1)将ismember与2000000一起使用速度更快,但占用更多内存
-运行时间-0.2306秒-或-0.0038分钟-
总计为1500001个元素,使用106000008字节

2) 使用intersect with 2000000速度较慢,但占用的内存较少。
-运行时间-0.3057秒-或-0.0051分钟-
总计1174947个元素,使用93992376字节

3) 将bskfun与100000一起使用会产生一个错误:内存不足或维度对于octave的索引类型太大

首次测试结果:

clear all, clc,  tic, clf; 
num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA1,idB1] = ismember(array(:,1),lookupval);
sort_comb_array(idB1(idA1),2) = array(idA1,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>


   finally Done-elapsed time -0.2306sec- or -0.0038mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name                  Size                     Bytes  Class
   ==== ====                  ====                     =====  ===== 
        a1              2000000x1                   16000000  double
        a2              2000000x1                   16000000  double
        array           2000000x2                   32000000  double
        idA1            2000000x1                    2000000  logical
        idB1            2000000x1                   16000000  double
        lookupval       1000000x1                    8000000  double
        num_to_test           1x1                          8  double
        sort_comb_array 1000000x2                   16000000  double

Total is 15000001 elements using 106000008 bytes
========================================================================
clear all, clc,  tic, clf; 

num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
output = zeros(length(lookupval),2);
output(:,1) = lookupval;
[c a b ] = intersect(array(:,1),lookupval);
output(b,2) =array(a,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>
finally Done-elapsed time -0.3057sec- or -0.0051mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name              Size                     Bytes  Class
   ==== ====              ====                     =====  ===== 
        a            250005x1                    2000040  double
        a1          2000000x1                   16000000  double
        a2          2000000x1                   16000000  double
        array       2000000x2                   32000000  double
        b            250005x1                    2000040  double
        c            250005x1                    2000040  double
        lookupval   1000000x1                    8000000  double
        num_to_test       1x1                          8  double
        output      1000000x2                   16000000  double

Total is 11750016 elements using 94000128 bytes


=======================================================================
第二次测试结果:

clear all, clc,  tic, clf; 
num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA1,idB1] = ismember(array(:,1),lookupval);
sort_comb_array(idB1(idA1),2) = array(idA1,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>


   finally Done-elapsed time -0.2306sec- or -0.0038mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name                  Size                     Bytes  Class
   ==== ====                  ====                     =====  ===== 
        a1              2000000x1                   16000000  double
        a2              2000000x1                   16000000  double
        array           2000000x2                   32000000  double
        idA1            2000000x1                    2000000  logical
        idB1            2000000x1                   16000000  double
        lookupval       1000000x1                    8000000  double
        num_to_test           1x1                          8  double
        sort_comb_array 1000000x2                   16000000  double

Total is 15000001 elements using 106000008 bytes
========================================================================
clear all, clc,  tic, clf; 

num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
output = zeros(length(lookupval),2);
output(:,1) = lookupval;
[c a b ] = intersect(array(:,1),lookupval);
output(b,2) =array(a,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>
finally Done-elapsed time -0.3057sec- or -0.0051mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name              Size                     Bytes  Class
   ==== ====              ====                     =====  ===== 
        a            250005x1                    2000040  double
        a1          2000000x1                   16000000  double
        a2          2000000x1                   16000000  double
        array       2000000x2                   32000000  double
        b            250005x1                    2000040  double
        c            250005x1                    2000040  double
        lookupval   1000000x1                    8000000  double
        num_to_test       1x1                          8  double
        output      1000000x2                   16000000  double

Total is 11750016 elements using 94000128 bytes


=======================================================================

这是一个测试Divakar建议我做,看看它的速度需要倍频程3.8.1运行这个。下面是结果和代码

1)将ismember与2000000一起使用速度更快,但占用更多内存
-运行时间-0.2306秒-或-0.0038分钟-
总计为1500001个元素,使用106000008字节

2) 使用intersect with 2000000速度较慢,但占用的内存较少。
-运行时间-0.3057秒-或-0.0051分钟-
总计1174947个元素,使用93992376字节

3) 将bskfun与100000一起使用会产生一个错误:内存不足或维度对于octave的索引类型太大

首次测试结果:

clear all, clc,  tic, clf; 
num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA1,idB1] = ismember(array(:,1),lookupval);
sort_comb_array(idB1(idA1),2) = array(idA1,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>


   finally Done-elapsed time -0.2306sec- or -0.0038mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name                  Size                     Bytes  Class
   ==== ====                  ====                     =====  ===== 
        a1              2000000x1                   16000000  double
        a2              2000000x1                   16000000  double
        array           2000000x2                   32000000  double
        idA1            2000000x1                    2000000  logical
        idB1            2000000x1                   16000000  double
        lookupval       1000000x1                    8000000  double
        num_to_test           1x1                          8  double
        sort_comb_array 1000000x2                   16000000  double

Total is 15000001 elements using 106000008 bytes
========================================================================
clear all, clc,  tic, clf; 

num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
output = zeros(length(lookupval),2);
output(:,1) = lookupval;
[c a b ] = intersect(array(:,1),lookupval);
output(b,2) =array(a,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>
finally Done-elapsed time -0.3057sec- or -0.0051mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name              Size                     Bytes  Class
   ==== ====              ====                     =====  ===== 
        a            250005x1                    2000040  double
        a1          2000000x1                   16000000  double
        a2          2000000x1                   16000000  double
        array       2000000x2                   32000000  double
        b            250005x1                    2000040  double
        c            250005x1                    2000040  double
        lookupval   1000000x1                    8000000  double
        num_to_test       1x1                          8  double
        output      1000000x2                   16000000  double

Total is 11750016 elements using 94000128 bytes


=======================================================================
第二次测试结果:

clear all, clc,  tic, clf; 
num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
sort_comb_array = [lookupval zeros(size(lookupval))];
[idA1,idB1] = ismember(array(:,1),lookupval);
sort_comb_array(idB1(idA1),2) = array(idA1,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>


   finally Done-elapsed time -0.2306sec- or -0.0038mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name                  Size                     Bytes  Class
   ==== ====                  ====                     =====  ===== 
        a1              2000000x1                   16000000  double
        a2              2000000x1                   16000000  double
        array           2000000x2                   32000000  double
        idA1            2000000x1                    2000000  logical
        idB1            2000000x1                   16000000  double
        lookupval       1000000x1                    8000000  double
        num_to_test           1x1                          8  double
        sort_comb_array 1000000x2                   16000000  double

Total is 15000001 elements using 106000008 bytes
========================================================================
clear all, clc,  tic, clf; 

num_to_test=2000000 %amount of numbers to test
a1=(1:1:num_to_test)';
a2=(a1.*num_to_test);
array=[a1,a2]; %array where values are stored

lookupval=(randperm(num_to_test,num_to_test/2)/4)'; %lookup these random vaules of intergers and floats and get another value

lookupval = sort(lookupval);
output = zeros(length(lookupval),2);
output(:,1) = lookupval;
[c a b ] = intersect(array(:,1),lookupval);
output(b,2) =array(a,2);

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

whos

>>>num_to_test =  2000000
>>>
finally Done-elapsed time -0.3057sec- or -0.0051mins- or -0.0001hours-
>>>Variables in the current scope:

   Attr Name              Size                     Bytes  Class
   ==== ====              ====                     =====  ===== 
        a            250005x1                    2000040  double
        a1          2000000x1                   16000000  double
        a2          2000000x1                   16000000  double
        array       2000000x2                   32000000  double
        b            250005x1                    2000040  double
        c            250005x1                    2000040  double
        lookupval   1000000x1                    8000000  double
        num_to_test       1x1                          8  double
        output      1000000x2                   16000000  double

Total is 11750016 elements using 94000128 bytes


=======================================================================

谢谢你的帮助。我在线运行了您的代码,但输出不匹配(它使所有查找值都为0)。我是否遗漏了什么?这是我运行ideone.com的链接/bxMhig@RickT我很想看看另一个基于
ismember
的解决方案在这个问题的八度音阶上的表现@Divakar Sure测试并比较它们now@Divakar我把结果发布为answer@RickT请确保在开始新方法之前清除内存,并确保有足够的迭代次数使计时在1秒左右或超过1秒。谢谢您的帮助。我在线运行了您的代码,但输出不匹配(它使所有查找值都为0)。我是否遗漏了什么?这是我运行ideone.com的链接/bxMhig@RickT我很想看看另一个基于
ismember
的解决方案在这个问题的八度音阶上的表现@Divakar Sure测试并比较它们now@Divakar我把结果发布为answer@RickT确保在开始新方法之前清除内存,并确保足够的迭代次数,以使计时在1秒左右或超过1秒。