Доступ к матричному элементу в состоянии - PullRequest
1 голос
/ 15 октября 2019

Я пытаюсь сократить вычислительное время моего кода MatLab. Для этого я использую MatLab profiler .

В некоторых функциях я был в такой же ситуации. Я зацикливаюсь на сетке (2D матрица) и проверяю, имеет ли каждая ячейка (или нет) некоторые значения (по два каждый раз). И состояние занимает много времени. Большую часть времени тратит на эти функции.

Вот пример из моего кода:

  time      Calls    line
                      16   function tGrid=some_compute(grid, tGrid, trans)
  0.005       125     17     global depth width tWidth 
                      18
< 0.001       125     19     for i=1:depth 
  0.022    125000     20       for j=1:width 
  2.270  37500000     21         if (grid(i, j)~=0 && grid(i, j)~=1) 
                      22
                      23           % Get the transformed coordinates of the current cell
  0.864     79997     24           [x, y]=get_trans(trans, i, j); 
                      25
  0.006     79997     26           if (x~=-1 && y~=-1) 
  0.006     79992     27             tGrid(x, y)=grid(i, j); 
  0.004     79992     28           end % If x~=-1 && y~=-1 
  0.004     79997     29         end % If grid~=0 && grid~=1 
  1.933  37500000     30       end % For j=width 
  0.008    125000     31     end % For i=depth 
                      32
< 0.001       125     33   end

Эта функция в общей сложности занимает 5,24 с для 125 вызовов.

Как мы видим, это строка 21, которая занимает больше времени для выполнения. В то время как к условию grid(i, j) обращаются дважды, и он также используется в строке 27, я предположил, что, предварительно сохранив его в переменной, он ускорит мой код.

Итак, я сделал этопростая модификация:

  time      Calls    line
                      16   function tGrid=some_compute(grid, tGrid, trans)
  0.005       125     17     global depth width tWidth
                      18
< 0.001       125     19     for i=1:depth
  0.021    125000     20       for j=1:width
  2.062  37500000     21         val=grid(i, j);
  1.681  37500000     22         if (val~=0 && val~=1)
                      23
                      24           % Get the transformed coordinates of the current cell
  0.793     79997     25           [x, y]=get_trans(trans, i, j);
                      26
  0.005     79997     27           if (x~=-1 && y~=-1)
  0.005     79992     28             tGrid(x, y)=val;
  0.004     79992     29           end % If x~=-1 && y~=-1
  0.004     79997     30         end % If grid~=0 && grid~=1
  1.731  37500000     31       end % For j=width
  0.007    125000     32     end % For i=depth
                      33
< 0.001       125     34   end

И теперь эта функция занимает в общей сложности 6,32 с для 125 вызовов.

Как мы видим, получение значения ячейки занимает столько же времени, сколько и получениеэто дважды и сравните его с двумя значениями. И строка 22 if такая же медленная, как и в первой версии. Я не понимаю почему.

Ответы [ 2 ]

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

получение значения ячейки занимает столько же времени, сколько получение его дважды и сравнение с двумя значениями. [...] Я не понимаю, почему.

Это потому, что ваш код запускается в JIT (компиляторе точно в срок). Этот компилятор оптимизирует ваш код. Хотя не задокументировано, как именно это работает и какие оптимизации реализованы, из вашего эксперимента кажется очевидным, что grid(i, j)~=0 && grid(i, j)~=1 оптимизирован для получения значения grid(i,j) только один раз.

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

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

Если я не просчитался, вы используете матрицу плотная 1000x300, которая представляет собой массив из 300 000 чисел с плавающей запятой.

Из этой строки

2.062  37500000     21         val=grid(i, j);

вы можете рассчитать, что одно выполнение занимает около 55 наносекунд (время / вызовы * 10 ^ 9), что довольно много для простого доступа к данным. Если у вас процессор с частотой 2 ГГц, цикл обработки занимает 0,5 наносекунды. Это было бы 110 циклов. Однако, поскольку вы используете огромную плотную матрицу, вы, вероятно, сталкиваетесь здесь с большим количеством кеш-пропусков. Чтобы быть уверенным, резко уменьшите размер матрицы (начните с 40x12) и рассчитайте время на выполнение. Если у вас есть проблема с пропуском кэша, она должна уменьшиться примерно до 1-2 наносекунд.

В случае, если пропадание кэша действительно является проблемой, я боюсь, что на самом деле не существует простого решения вашей проблемы, так как оно требует реорганизацииваши данные в дружественной памяти. Тот факт, что Matlab является языком сценариев, не облегчает его, потому что у вас нет компилятора, который выполняет оптимизацию для вас. Вы можете попробовать переключить внутренний и внешний цикл и надеяться, что схема доступа к памяти улучшится.

Привет

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