【问题标题】:How to avoid sub2ind and decrease execution time in manipulating multidimensional arrays using original indexes如何在使用原始索引操作多维数组时避免 sub2ind 并减少执行时间
【发布时间】:2016-08-24 06:21:59
【问题描述】:

我希望得到您的建议,以使我的代码更快(更优雅)。特别是,根据 matlab 分析器,sub2ind(和 if 循环)会显着减慢它的速度。我会尽量简单地解释我的代码需要什么。

为简单起见,假设我有以下问题。

每个城市的每个公民都有一辆特定品牌和特定颜色的汽车。 我想要的是一个 4D 多维数组 Data_4D(City,Citizen,Car_brand,Car_color),我可以仅使用这四个维度作为索引来操作(读取和修改)它。

然后,我想用

将我的多维数组重塑为一维数组 Data_1D
length(Data_1D)=(City*Citizen*Car_brand*Car_color)

元素的顺序必须遵循索引规则: 假设City=2, Citizen=2, Car_brand=2, Car_color=2的示例;

    Data_1D(1)=Data_4D(1,1,1,1)
    Data_1D(2)=Data_4D(1,1,1,2)
    Data_1D(3)=Data_4D(1,1,2,1)
    Data_1D(4)=Data_4D(1,1,2,2)
    Data_1D(5)=Data_4D(1,2,1,1)
    Data_1D(6)=Data_4D(1,2,1,2)
    Data_1D(7)=Data_4D(1,2,2,1)
    Data_1D(8)=Data_4D(1,2,2,2)
    Data_1D(9)=Data_4D(2,1,1,1)
    Data_1D(10)=Data_4D(2,1,1,2)
    Data_1D(11)=Data_4D(2,1,2,1)
    Data_1D(12)=Data_4D(2,1,2,2)
    Data_1D(13)=Data_4D(2,2,1,1)
    Data_1D(14)=Data_4D(2,2,1,2)
    Data_1D(15)=Data_4D(2,2,2,1)
    Data_1D(16)=Data_4D(2,2,2,2)

之后我会得到这个一维数组,形状如上,我需要创建一个矩阵Matrix_Final( NRows,length(Data_1D)),其中每一行都是一个数组Data_1D。在每一行 NRows 中,数组 Data_1D 将具有相同数量的元素,但具有不同的值。
行数还取决于 City、Citizen、Car_brand、Car_color 四个维度中的一些(或全部)(尊重与 Data_1D 相同的索引规则),并且每行中构建的数组也必须根据矩阵行(通过使用四个索引,这是 NRows 和 Data_1D 的通用规则)。

示例: 假设City=2, Citizen=2, Car_brand=2, Car_color=2; 假设 NRows 取决于所有四个维度。 我会有Matrix_Final( length(DATA_1D), length(DATA_1D))。 我希望我的数组 DATA_1D 的所有数据都是零,除了一个元素,它必须是具有相同索引 values(City,Citizen,Car_brand,Car_color)NRows(City,Citizen,Car_brand,Car_color) 的元素 所以在NRows(1) 行,只有Data_1D(1) 是非零的。对于这个例子,结果是一个眼睛矩阵。

clc
  clear all
  %Dimensions Definition
  City=2;
  Citizen=2;
  Car_brand=2;
  Car_color=2;
  %Length of Data
  Length_Data_1D=City*Citizen*Car_brand*Car_color;
  %preallocation Matrix_Final
  Matrix_Final=zeros(City*Citizen*Car_brand*Car_color, Length_Data_1D);
  %indexes of the dimensions
  indexes_array_carcolor=repmat(repelem([1:Car_color], 1), [1 City*Citizen*Car_brand]);
  indexes_array_carbrand=repmat(repelem([1:Car_brand], Car_color), [1 City*Citizen]);
  indexes_array_citizen=repmat(repelem([1:Citizen],Car_brand*Car_color),[1 City]);
  indexes_array_city=repmat(repelem([1:City],Citizen*Car_brand*Car_color),[1 1]);
  %Initializing loop variable
  column_Matrix_final=1;

  for CITY_selected=1:City
     for CITIZEN_selected=1:Citizen 
         for CAR_BRAND_selected=1:Car_brand
           for CAR_COLOR_selected=1:Car_color
            %Data_4D Construction
            Data_4D=zeros(City,Citizen,Car_brand,Car_color);
              for city=1:length(indexes_array_city)
                for citizen=1:length(indexes_array_citizen)
                    for car_brand=1:length(indexes_array_carbrand)
                        for car_color=1:length(indexes_array_carcolor)
                            if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
                                  && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
                                  indexes_array_carcolor(car_color)==CAR_COLOR_selected)
                          Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
                              indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1; 
                            end
                      end
                  end
              end
       end
      %Data_4D transformation into array Data_1D
      Data_1D=zeros(1,City*Citizen*Car_brand*Car_color);
      tic=1;
      for city=1:City
          for citizen=1:Citizen
              for car_brand=1:Car_brand
                  for car_color=1:Car_color
                      Data_1D(tic)=Data_4D(city,citizen,car_brand,car_color);
                      tic=tic+1;
                  end
              end
          end
      end
      %Adding Data_1D to the next for of Matrix_Final
      Matrix_Final(column_Matrix_final,:)=Data_1D;
      column_Matrix_final=column_Matrix_final+1;
      %Display of the four most external loops indexes to show code
      %advancement
       CAR_COLOR_selected
     end
         CAR_BRAND_selected
  end
      CITIZEN_selected
 end
         CITY_selected 
end
      spy(Matrix_Final)

如果您添加例如

  && indexes_array_carcolor(car_color)==2 

在 if 循环中,只有NRows(City,Citizen,Car_brand,Car_color=2) 中的Data_1D(City,Citizen,Car_brand,Car_color=2) 的元素不为零。

我想知道是否有更快的方法来解决问题,但保持使用四个索引(City、Citizen、Car_brand、Car_color)操作 Data_1D 和 Matrix_Final 的相同能力以及将 NRows 和使用这四个索引的 Data_1D 的元素。

感谢您的帮助!

【问题讨论】:

  • 你为什么在那里使用sub2indData_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),... indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1; 我猜Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),... indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=1; 会产生完全相同的结果
  • 我不明白你创建矩阵Data_4D 的方式,好像你多次将相同的索引覆盖到 1
  • 结果不总是眼睛矩阵吗?
  • 我认为你的代码没有做你想做的事。对于给定的(City,Citizen),您可能只想绘制一个Car_Brand 和一个Car_Color
  • @BillBokeey:感谢您的回答。每个公民都可以拥有多辆不同颜色的汽车(也可以是不同颜色的同一辆车)。

标签: matlab matrix multidimensional-array indexing


【解决方案1】:

这就是你的编码方式

if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
     && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
   indexes_array_carcolor(car_color)==CAR_COLOR_selected)
   Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
   indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1; 
end

另一种方式1

if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
     && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
    indexes_array_carcolor(car_color)==CAR_COLOR_selected)
    Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
    indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=1; 
end

另一种方式2

Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
     indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=double((indexes_array_city(city)==CITY_selected)& ...
                                  (indexes_array_citizen(citizen)==CITIZEN_selected)& ...
                                  (indexes_array_carbrand(car_brand)==CAR_BRAND_selected)& ...
                                  (indexes_array_carcolor(car_color)==CAR_COLOR_selected));

这三个都将产生相同的结果。尝试哪个更快并使用它。

%% Data_4D transformation into array Data_1D
Data_4D_size=size(Data_4D);
Data_1D_size=prod(Data_4D_size);
temp = permute(Data_4D, [4 3 2 1]);
Data_1D=reshape(temp,Data_1D_size,1);

将此用于 4D 到 1D 的转换

如果还需要更快的速度。将其编译为 mex。编译后的代码运行速度更快。

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 2019-06-03
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    相关资源
    最近更新 更多