如何避免在MATLAB中构造这些网格变量?

时间:2018-10-06 18:52:31

标签: matlab memory

我分两个步骤进行了以下计算:

  1. 最初,我创建了一组4个网格矢量,每个矢量从-22

    u11grid=[-2:0.1:2];
    u12grid=[-2:0.1:2];
    u22grid=[-2:0.1:2];
    u21grid=[-2:0.1:2];
    [ca, cb, cc, cd] = ndgrid(u11grid, u12grid, u22grid, u21grid);
    u11grid=ca(:);
    u12grid=cb(:);
    u22grid=cc(:);
    u21grid=cd(:);
    %grid=[u11grid u12grid u22grid u21grid]
    sg=size(u11grid,1);
    
  2. 接下来,我有一种算法,向共享特定结构的equalorder行分配相同的索引(grid):

    U1grid=[-u11grid -u21grid -u12grid -u22grid  Inf*ones(sg,1) -Inf*ones(sg,1)];
    U2grid=[u21grid-u11grid -u21grid u22grid-u12grid -u22grid Inf*ones(sg,1) -Inf*ones(sg,1)]; 
    s1=size(U1grid,2);
    s2=size(U2grid,2);
    %-------------------------------------------------------
    %sortedU1grid gives U1grid with each row sorted from smallest to largest
    %for each row i of sortedU1grid and for j=1,2,...,s1 index1(i,j) gives
    %the column position 1,2,...,s1 in U1grid(i,:) of sortedU1grid(i,j)
    
    [sortedU1grid,index1] = sort(U1grid,2); 
    
    %for each row i of sortedU1grid, d1(i,:) is a 1x(s1-1) row of ones and zeros
    % d1(i,j)=1 if sortedU1grid(i,j)-sortedU1grid(i,j-1)=0 and d1(i,j)=0  otherwise
    
    d1 = diff(sortedU1grid,[],2) == 0;
    %-------------------------------------------------------
    %Repeat for U2grid
    [sortedU2grid,index2] = sort(U2grid,2);
    d2 = diff(sortedU2grid,[],2) == 0;
    %-------------------------------------------------------
    %Assign the same index to the rows of grid sharing the same "ordering"
    [~,~,equalorder] = unique([index1 index2 d1 d2],'rows', 'stable'); %sgx1 
    

我的问题:没有步骤1中的网格矢量的初始构造,是否可以在步骤2中计算算法??我之所以这样问,是因为步骤1基本上会产生4组的笛卡尔积,因此会占用大量内存。

解决方案不应依赖U1gridU2grid的特定内容,因为这部分会在我的实际代码中发生变化。更清楚地说:U1gridU2grid总是从u11grid, ..., u21grid派生而来;但是,在我的实际代码中,从u11grid, ..., u21grid派生它们的方式比我在这里报告的要复杂一些。

2 个答案:

答案 0 :(得分:2)

Cris Luengo mentions in a comment一样,您总是要在速度和内存之间进行权衡。也就是说,您有一个选择是仅在需要时计算4个网格变量(u11grid u12grid u22grid u21grid)中的每一个,而不是一次计算并存储它们。您将节省内存,但如果多次重新计算每次,则会失去速度。

我想出的解决方案涉及为四个网格变量中的每个变量创建一个anonymous function等效项,使用repmatrepelem的组合分别计算每个变量,而不是{{3} }一起计算它们:

u11gridFcn = @() repmat((-2:0.1:2).', 41.^3, 1);
u12gridFcn = @() repmat(repelem((-2:0.1:2).', 41), 41.^2, 1);
u22gridFcn = @() repmat(repelem((-2:0.1:2).', 41.^2), 41, 1);
u21gridFcn = @() repelem((-2:0.1:2).', 41.^3);
sg = 41.^4;

然后,您可以通过将U1gridU2grid中4个网格变量的每种用法替换为相应的函数调用来使用它们。对于上面的特定示例,这将是U1gridU2grid的新代码(另请注意,使用ndgrid代替了Inf*ones(...),这是一个小细节):

U1grid = [-u11gridFcn() ...
          -u21gridFcn() ...
          -u12gridFcn() ...
          -u22gridFcn() ...
          inf(sg, 1) ...
          -inf(sg, 1)];
U2grid = [u21gridFcn()-u11gridFcn() ...
          -u21gridFcn() ...
          u22gridFcn()-u12gridFcn() ...
          -u22gridFcn() ...
          inf(sg, 1) ...
          -inf(sg, 1)];

在此示例中,避免了存储4个网格变量所需的内存,但是u11gridu12grid的值将分别计算两次,而u21grid和{ {1}}将分别计算三次。可能需要进行少量时间权衡,以节省大量内存。

答案 1 :(得分:1)

您也许可以删除ndgrid,但这不是此代码的存储瓶颈,而是对大型矩阵unique上的A = [index1 index2 d1 d2]的调用。 A的大小为2825761 x 22(比网格大得多),看来unique甚至可以在内部复制A。我能够避免使用

    [sorted, ind] = sortrows([index1 index2 d1 d2]);
    change = [1; any(diff(sorted), 2)];
    uniqueInd = cumsum(change);
    equalorder(ind) = uniqueInd;
    [~, ~, equalorder] = unique(equalorder, 'stable');

最后一行仍然是内存瓶颈,仅当您想要与代码产生相同的编号时才需要。如果可以进行任何唯一排序,则可以跳过它。通过谨慎地clear使变量不再需要时,它们可以进一步减少内存占用。