Как я могу избежать создания этих переменных сетки в MATLAB? - PullRequest
0 голосов
/ 06 октября 2018

У меня есть следующие вычисления в два этапа:

  1. Изначально я создал набор из 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);
    
  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 
    

Мой вопрос: есть ли способ вычислить алгоритм на шаге 2 без начального построения векторов сетки на шаге 1 ?Я спрашиваю об этом, потому что шаг 1 занимает много памяти, учитывая, что он в основном генерирует декартово произведение из 4 наборов.

Решение не должно полагаться на конкретное содержание U1grid и U2grid как этой частиизменения в моем реальном коде.Для большей ясности: U1grid и U2grid ВСЕГДА получены из u11grid, ..., u21grid;однако способ, которым они получены из u11grid, ..., u21grid, немного более сложен в моем реальном коде из того, что я сообщил здесь.

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Как Крис Луенго упоминает в комментарии , вы всегда будете иметь дело с компромиссом между скоростью и памятью.Тем не менее, у вас есть один вариант - вычислять каждую из ваших 4 переменных сетки (u11grid u12grid u22grid u21grid), когда это необходимо, вместо того, чтобы вычислять их один раз и сохранять.Вы сэкономите на памяти, но потеряете скорость, если будете повторно вычислять каждый из них несколько раз.

Решение, которое я придумал, заключается в создании анонимной функции эквивалента для каждой из 4 переменных сетки,используя комбинации repmat и repelem для вычисления каждого по отдельности вместо ndgrid для вычисления их всех вместе:

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 их соответствующим вызовом функции.Для приведенного выше конкретного примера это будет новый код для U1grid и U2grid (обратите внимание также на использование inf(...) вместо 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 и u22grid - каждый.рассчитать три раза.Вероятно, небольшой компромисс по времени для потенциально значительной экономии памяти.

0 голосов
/ 15 октября 2018

Вы можете удалить ndgrid, но это не узкое место в памяти этого кода, а вызов unique на большой матрице A = [index1 index2 d1 d2].Размер A равен 2825761 на 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 переменные скоро станут ненужными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...