我分两个步骤进行了以下计算:
最初,我创建了一组4个网格矢量,每个矢量从-2
到2
:
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);
接下来,我有一种算法,向共享特定结构的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组的笛卡尔积,因此会占用大量内存。
解决方案不应依赖U1grid
和U2grid
的特定内容,因为这部分会在我的实际代码中发生变化。更清楚地说:U1grid
和U2grid
总是从u11grid, ..., u21grid
派生而来;但是,在我的实际代码中,从u11grid, ..., u21grid
派生它们的方式比我在这里报告的要复杂一些。
答案 0 :(得分:2)
与Cris Luengo mentions in a comment一样,您总是要在速度和内存之间进行权衡。也就是说,您有一个选择是仅在需要时计算4个网格变量(u11grid u12grid u22grid u21grid
)中的每一个,而不是一次计算并存储它们。您将节省内存,但如果多次重新计算每次,则会失去速度。
我想出的解决方案涉及为四个网格变量中的每个变量创建一个anonymous function等效项,使用repmat
和repelem
的组合分别计算每个变量,而不是{{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;
然后,您可以通过将U1grid
和U2grid
中4个网格变量的每种用法替换为相应的函数调用来使用它们。对于上面的特定示例,这将是U1grid
和U2grid
的新代码(另请注意,使用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个网格变量所需的内存,但是u11grid
和u12grid
的值将分别计算两次,而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
使变量不再需要时,它们可以进一步减少内存占用。