Есть ли более эффективный способ выполнения нескольких вложенных циклов for в Matlab? - PullRequest
1 голос
/ 05 апреля 2019

У меня есть небольшой логический массив (A) размером 256x256x256 с неизвестной формой где-то в массиве. Также есть меньший двойной массив (se) размером 13x13x13. В середине массива определен куб логических единиц (se).

Мне нужно запустить каждый логический элемент в A, и для каждого логического элемента в A меньший массив se должен добавить свои элементы в A. Значение расширения формы A на se.

Вот что я получил до сих пор. Он работает, но имеет очень плохую производительность по скорости.

У кого-нибудь есть предложения по ускорению этой задачи по кодированию?

[p, q, r] = size(se);
[m, n, o] = size(A);

temp = zeros(m, n, o);
for i = 1:m
    for j = 1:n
        for k = 1:o
            if img_g(i, j, k) == 1
                for s = 1:p
                    for t = 1:q
                        for u = 1:r
                            if se(s, t, u) == 1
                                c = i + s;
                                d = j + t;
                                e = k + u;
                                temp(c, d, e) = 1;
                            end
                        end
                    end
                end
            end
        end
    end
end
B = temp;

Я очень благодарен за любую помощь и предложения, которые улучшают мои навыки программирования.

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

Я не уверен на 100%, что это именно то, о чем вы просите (поскольку я не совсем понимаю, что делает ваш код), но, возможно, методология даст некоторое вдохновение.

Я не сгенерировал "логический" A, а был случайным, и я установил внутри куб, равный 1. Аналогично для se. Я использую meshgrid, чтобы получить массивы, соответствующие индексам, и использую mask логического индексирования. (возможно, мой mask это то, что у вас есть для A в первую очередь?)

A = rand(255,255,255);
A(40:50, 23:33, 80:100) = 1;
mask = (A==1);

[I,J,K] = meshgrid(1:255);

se = rand(13,13,13);
se(4:6, 3:7, 2:8) = 1;
se_mask = (se==1);

[se_I, se_J, se_K] = meshgrid(1:13);

Здесь я предполагаю, что куб в A достаточно далеко от любого ребра (скажем, 13 пробелов), поэтому мы не получим c, d или e больше, чем 255.

Я сплющил mask в вектор-строку, поэтому find дает один индекс ii, который мы можем использовать для ссылки на любую точку в A, затем на исходные i, j и k индексы в I(ii), J(ii) и K(ii) соответственно. Аналогично для se_I и т. Д.

temp = zeros(255, 255, 255);
for ii=find(mask(:).')
  for jj=find(se_mask(:).')
    c = I(ii) + se_I(jj);
    d = J(ii) + se_J(jj);
    e = K(ii) + se_K(jj);
    temp(c,d,e) = 1;
  end % for
end % for

Матрицы I, J, K, se_I, se_J и se_K являются регулярными, поэтому, если их создание / хранение становится узким местом, вы можете написать функции для их замены. Матрица temp может быть очень разреженной в зависимости от размера ваших кубиков, поэтому вы можете использовать sparse.

Я не сравнивал время с вашим решением.

0 голосов
/ 05 апреля 2019

в зависимости от процессора, который вы используете, вы можете по крайней мере использовать «parfor» для внешнего цикла (первый цикл).это позволяет выполнять параллельные вычисления и повышает производительность благодаря количеству физических ядер, полученных вашим процессором.

...