矢量化嵌套的if语句

时间:2016-06-30 14:14:47

标签: performance matlab vectorization

问题 我正在处理大约1800万个点数据集,这些数据集贯穿不同的流程。在配置文件查看器中,我发现我的一个瓶颈是这部分代码,因此我想知道是否可以对多个if语句进行矢量化。

代码

WA=zeros(size(NB_list_z,1),3);
for i=1:size(NB_list_z,1);
    if (NB_list_z(i,2)==0||NB_list_z(i,3)==0);        
    WA(i,1)=BMLS(NB_list_z(i,1),5);

    else
       if (BMLS(NB_list_z(i,3),5)>=COG);
       WA(i,1)=(BMLS(NB_list_z(i,3),5)+BMLS(NB_list_z(i,2),5)+BMLS(NB_list_z(i,1),5))/3;    
            if (WA(i,1)<COG);
                if (BMLS(NB_list_z(i,2),5)>=COG);
               WA(i)=(BMLS(NB_list_z(i,2),5)+BMLS(NB_list_z(i,1),5))/2;                           
                    if (WA(i,1)<COG);
                  WA(i,1)=BMLS(NB_list_z(i,1),5);                  
                    end 
                else
                WA(i,1)=BMLS(NB_list_z(i,1),5);                
                end 
            end 
        else
             if (BMLS(NB_list_z(i,2),5)>=COG);
               WA(i,1)=(BMLS(NB_list_z(i,2),5)+BMLS(NB_list_z(i,1),5))/2;

                  if (WA(i,1)<COG);
                  WA(i,1)=BMLS(NB_list_z(i,1),5);                 
                 end 
             else
                WA(i,1)=BMLS(NB_list_z(i,1),5);               
             end          
       end
    end  
end 

代码说明

NB_list_z包含第一列中各点的邻居的索引(在z方向上 - 每个点最多可以有两个点。) BMLS包含我要检查的阈值。 COG是阈值。 考虑最低的块= Block1,上面的一个= Block2,一个上面的Block3。

如果上面没有邻居,则第一个if子句将值设置为Block1的值。

之后我想以最有利可图的方式为我组合块。 意味着如果块3 + 2 + 1高于阈值我想要将它们全部包括在内,但最高块(这里是块3)也必须单独超过阈值。 如果不是那么2 + 1具有相同的条件,如果不是那么只有1。 上面的代码在小数据集上运行得非常好,但是开始花费大量时间来处理更大的数据集。

问题

我是“代码优化”和“矢量化”的新手,在这个意义上我只是从它开始。我发现了一些关于删除for循环等的条目,但我找不到任何要删除的东西或只是多个if-clause。因此,问题是可以对嵌套的if子句进行矢量化吗?

1 个答案:

答案 0 :(得分:1)

代码有点太长了,无法在这个论坛上重写,如果没有针对具有预期输出的测试数据进行测试,那么太长时间也不会重写。但是,让我来谈谈&#34;矢量化&#34;代替。

什么是矢量化?

因此,当我们在MATLAB中讨论矢量化时,我们通常意味着我们在矢量上应用某些操作而不是矢量中的每个元素。有点过分充实我们可以看到它好像我们,而不是在向量中的每个元素上应用操作,而是使用以向量作为输入的函数。为了使其有效,操作需要MATLAB支持。我的意思是繁重的工作应该由编译文件(mex文件)执行。

怎么做?

当你想将它应用于向量中的所有元素时,它非常简单。例如,而不是做,

a = 1:2:20;
total = 0;
for k = a %(range-based)
    total = total + a;
end
%for ind = 1:length(a) %(same result)
%    total = total + a(ind);
%end

可以这样做,

a = 1:2:20;
total = sum(a);

如果循环中有if语句,仍然可以对此进行向量化。假设您要分别对小于11且大于11的所有元素求和,

a = 1:2:20
total1 = sum(a(a<11));
total2 = sum(a(a>11));

但是,如果嵌套了if语句,它会变得更复杂。您可能需要将操作拆分为多个表达式。 if语句的每个分支都需要单独处理。每个嵌套的if语句都需要被视为外部if语句的子集。因此,可以使用and&)处理它。

b = rand(10);
c = zeros(10);
c(b<0.5) = 0;
c(b>=0.5 & b<0.8) = 2*(c(b>=0.5 & b<0.8).^2);
c(b>=0.8) = 1;

我何时进行矢量化

如果函数仅使用几次并且执行足够快的&#34;则可能不值得向量化。在此之后,它成为复杂性和效率之间的权衡。如果在执行期间调用10000次,则在100秒内执行的函数可能仍然需要优化。通常,更通用的功能需要优化,因为这些功能似乎吸引了更多的函数调用。此外,如果您运行嵌套for循环,其中循环之间存在依赖关系,则这些函数往往难以向量化。

a = 2:2:20;
for (m=1:length(a))
    for (n=1:length(a))
        if (m~=n)
            a(n) = a(n)/2; 
        end
    end
    a(a>5) = 2*a(a>5);
end

这变得非常复杂,其中内部循环取决于外部循环的特定迭代。它仍然可以解决,但是你会遇到类似于找到双积分的正交参数化的问题。如果它不是绝对必要的话,它可能不值得付出努力,即使对它进行矢量化至关重要,仍然有必要以比矢量化这些循环更可矢量化的方式重新定义问题。

最后一句话

请注意,对于大型数据集,矢量化可能会生成大量元素的副本。确保您没有修改函数的输入,因为Matlab使用了copy-on-write。